Hi,

This diff adds client side certificate checks to httpd.  Most parts are
straight forward.  But, to transfer the whole certificate authority
store to the server process through the imsg infrastructure I had to
change this in an chunked transfer.

The Documentation of this feature is included in httpd.conf.5.

This time, I also extend an httpd tls regression tests to use a client
side certificate.  All tests pass :-)

If anything is wrong with this diff, just notify me, I will fix it.

Bye,
Jan

Index: config.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/config.c,v
retrieving revision 1.45
diff -u -p -r1.45 config.c
--- config.c    28 Apr 2016 14:20:11 -0000      1.45
+++ config.c    3 May 2016 19:51:57 -0000
@@ -236,51 +236,59 @@ config_settls(struct httpd *env, struct 
        struct server_config    *srv_conf = &srv->srv_conf;
        struct tls_config        tls;
        struct iovec             iov[2];
-       size_t                   c;
+       size_t                   n;
+       char                    *p;
 
        if ((srv_conf->flags & SRVFLAG_TLS) == 0)
                return (0);
 
        log_debug("%s: configuring TLS for %s", __func__, srv_conf->name);
 
-       if (srv_conf->tls_cert_len != 0) {
-               DPRINTF("%s: sending TLS cert \"%s[%u]\" to %s fd %d", __func__,
-                   srv_conf->name, srv_conf->id, ps->ps_title[PROC_SERVER],
-                   srv->srv_s);
-
-               memset(&tls, 0, sizeof(tls));
-               tls.id = srv_conf->id;
-               tls.tls_cert_len = srv_conf->tls_cert_len;
-
-               c = 0;
-               iov[c].iov_base = &tls;
-               iov[c++].iov_len = sizeof(tls);
-               iov[c].iov_base = srv_conf->tls_cert;
-               iov[c++].iov_len = srv_conf->tls_cert_len;
+       if ((p = malloc(srv_conf->tls_ca_len + srv_conf->tls_cert_len +
+           srv_conf->tls_key_len)) == NULL) {
+               log_warn("%s: failed to compose IMSG_CFG_TLS imsg for "
+                   "`%s'", __func__, srv_conf->name);
+               return (-1);
+       }
 
-               if (proc_composev(ps, PROC_SERVER, IMSG_CFG_TLS, iov, c) != 0) {
-                       log_warn("%s: failed to compose IMSG_CFG_TLS imsg for "
-                           "`%s'", __func__, srv_conf->name);
-                       return (-1);
-               }
+       memcpy(p, srv_conf->tls_ca, srv_conf->tls_ca_len);
+       n = srv_conf->tls_ca_len;
+       memcpy(p + n, srv_conf->tls_cert, srv_conf->tls_cert_len);
+       n += srv_conf->tls_cert_len;
+       memcpy(p + n, srv_conf->tls_key, srv_conf->tls_key_len);
+       n += srv_conf->tls_key_len;
+
+       /* send tls_config structure */
+       memset(&tls, 0, sizeof(tls));
+       tls.id = srv_conf->id;
+       tls.port = srv_conf->port;
+       memcpy(&tls.ss, &srv_conf->ss, sizeof(tls.ss));
+       tls.tls_ca_optional = srv_conf->tls_ca_optional;
+       tls.tls_ca_len = srv_conf->tls_ca_len;
+       tls.tls_cert_len = srv_conf->tls_cert_len;
+       tls.tls_key_len = srv_conf->tls_key_len;
+
+       if (proc_compose(ps, PROC_SERVER, IMSG_CFG_TLS, &tls, sizeof(tls)) != 
0) {
+               log_warn("%s: failed to compose IMSG_CFG_TLS imsg for "
+                   "`%s'", __func__, srv_conf->name);
+               return (-1);
        }
 
-       if (srv_conf->tls_key_len != 0) {
-               DPRINTF("%s: sending TLS key \"%s[%u]\" to %s fd %d", __func__,
-                   srv_conf->name, srv_conf->id, ps->ps_title[PROC_SERVER],
-                   srv->srv_s);
-
-               memset(&tls, 0, sizeof(tls));
-               tls.id = srv_conf->id;
-               tls.tls_key_len = srv_conf->tls_key_len;
-
-               c = 0;
-               iov[c].iov_base = &tls;
-               iov[c++].iov_len = sizeof(tls);
-               iov[c].iov_base = srv_conf->tls_key;
-               iov[c++].iov_len = srv_conf->tls_key_len;
+       iov[0].iov_base = &tls;
+       iov[0].iov_len = sizeof(tls);
+
+#define MSG_CHUNK_SIZE (MAX_IMSGSIZE - (ssize_t)IMSG_HEADER_SIZE - 
iov[0].iov_len)
+
+       /* transfer in chunks */
+       for (; n > 0; p += MSG_CHUNK_SIZE) {
+               size_t len = n > MSG_CHUNK_SIZE ? MSG_CHUNK_SIZE : n;
+               n -= len;
 
-               if (proc_composev(ps, PROC_SERVER, IMSG_CFG_TLS, iov, c) != 0) {
+               iov[1].iov_base = p;
+               iov[1].iov_len = len;
+
+               if (proc_composev(ps, PROC_SERVER, IMSG_CFG_TLS_CHNK, iov, 2)
+                   != 0) {
                        log_warn("%s: failed to compose IMSG_CFG_TLS imsg for "
                            "`%s'", __func__, srv_conf->name);
                        return (-1);
@@ -555,6 +563,52 @@ config_getserver(struct httpd *env, stru
 }
 
 int
+config_gettls_chunk(struct httpd *env, struct imsg *imsg)
+{
+       struct server_config    *srv_conf = NULL;
+       struct tls_config        tls_conf;
+       uint8_t                 *p = imsg->data;
+       size_t                   s = 0;
+
+       IMSG_SIZE_CHECK(imsg, &tls_conf);
+       memcpy(&tls_conf, p, sizeof(tls_conf));
+       s = sizeof(tls_conf);
+
+       if ((srv_conf = serverconfig_byid(tls_conf.id)) == NULL) {
+               log_debug("%s: server not found", __func__);
+               goto fail;
+       }
+
+#define CHUNK_CPY(dst, dst_len, dst_size, src, src_size, src_off)      \
+       do {                                                            \
+               if (dst_len < dst_size) {                               \
+                       size_t n = dst_size - dst_len;                  \
+                       if (n > src_size - src_off)                     \
+                               n = src_size - src_off;                 \
+                       memcpy(dst + dst_len, src + src_off, n);        \
+                       dst_len += n;                                   \
+                       src_off += n;                                   \
+               }                                                       \
+       } while(0)
+
+       CHUNK_CPY(srv_conf->tls_ca, srv_conf->tls_ca_len,
+           srv_conf->tls_ca_size, p, IMSG_DATA_SIZE(imsg), s);
+
+       CHUNK_CPY(srv_conf->tls_cert, srv_conf->tls_cert_len,
+           srv_conf->tls_cert_size, p, IMSG_DATA_SIZE(imsg), s);
+
+       CHUNK_CPY(srv_conf->tls_key, srv_conf->tls_key_len,
+           srv_conf->tls_key_size, p, IMSG_DATA_SIZE(imsg), s);
+
+#undef CHUNK_CPY
+
+       return (0);
+
+ fail:
+       return (-1);
+}
+
+int
 config_gettls(struct httpd *env, struct imsg *imsg)
 {
 #ifdef DEBUG
@@ -569,12 +623,6 @@ config_gettls(struct httpd *env, struct 
        memcpy(&tls_conf, p, sizeof(tls_conf));
        s = sizeof(tls_conf);
 
-       if ((IMSG_DATA_SIZE(imsg) - s) <
-           (tls_conf.tls_cert_len + tls_conf.tls_key_len)) {
-               log_debug("%s: invalid message length", __func__);
-               goto fail;
-       }
-
        if ((srv_conf = serverconfig_byid(tls_conf.id)) == NULL) {
                log_debug("%s: server not found", __func__);
                goto fail;
@@ -584,20 +632,25 @@ config_gettls(struct httpd *env, struct 
            ps->ps_title[privsep_process], ps->ps_instance,
            srv_conf->name, srv->srv_conf.id);
 
-       if (tls_conf.tls_cert_len != 0) {
-               srv_conf->tls_cert_len = tls_conf.tls_cert_len;
-               if ((srv_conf->tls_cert = get_data(p + s,
-                   tls_conf.tls_cert_len)) == NULL)
-                       goto fail;
-               s += tls_conf.tls_cert_len;
-       }
-       if (tls_conf.tls_key_len != 0) {
-               srv_conf->tls_key_len = tls_conf.tls_key_len;
-               if ((srv_conf->tls_key = get_data(p + s,
-                   tls_conf.tls_key_len)) == NULL)
-                       goto fail;
-               s += tls_conf.tls_key_len;
-       }
+       srv_conf->tls_ca_optional = tls_conf.tls_ca_optional;
+       srv_conf->tls_ca_len = 0;
+       srv_conf->tls_cert_len = 0;
+       srv_conf->tls_key_len = 0;
+
+       srv_conf->tls_ca_size = tls_conf.tls_ca_len;
+       srv_conf->tls_cert_size = tls_conf.tls_cert_len;
+       srv_conf->tls_key_size = tls_conf.tls_key_len;
+
+       free(srv_conf->tls_ca);
+       free(srv_conf->tls_cert);
+       free(srv_conf->tls_key);
+
+       if ((srv_conf->tls_ca = malloc(tls_conf.tls_ca_len)) == NULL)
+               goto fail;
+       if ((srv_conf->tls_cert = malloc(tls_conf.tls_cert_len)) == NULL)
+               goto fail;
+       if ((srv_conf->tls_key = malloc(tls_conf.tls_key_len)) == NULL)
+               goto fail;
 
        return (0);
 
Index: httpd.conf.5
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/httpd.conf.5,v
retrieving revision 1.73
diff -u -p -r1.73 httpd.conf.5
--- httpd.conf.5        9 May 2016 19:36:54 -0000       1.73
+++ httpd.conf.5        10 May 2016 16:18:04 -0000
@@ -498,6 +498,13 @@ Set the TLS configuration for the server
 These options are only used if TLS has been enabled via the listen directive.
 Valid options are:
 .Bl -tag -width Ds
+.It Ic ca Ar file Oo Ic optional Oc
+Specify a certificate authority for verifying client side certificates.
+.Ar file
+should contain a PEM encoded certificate of the certificate authority.
+The parameter
+.Ic optional
+does not requiring the client to send a certificate.
 .It Ic certificate Ar file
 Specify the certificate to use for this server.
 The
Index: httpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/httpd.h,v
retrieving revision 1.103
diff -u -p -r1.103 httpd.h
--- httpd.h     28 Apr 2016 14:20:11 -0000      1.103
+++ httpd.h     7 May 2016 02:53:08 -0000
@@ -203,6 +203,7 @@ enum imsg_type {
        IMSG_CTL_REOPEN,
        IMSG_CFG_SERVER,
        IMSG_CFG_TLS,
+       IMSG_CFG_TLS_CHNK,
        IMSG_CFG_MEDIA,
        IMSG_CFG_AUTH,
        IMSG_CFG_DONE,
@@ -424,14 +425,21 @@ struct server_config {
        uint32_t                 maxrequests;
        size_t                   maxrequestbody;
 
+       uint8_t                 *tls_ca;
+       size_t                   tls_ca_len;
+       size_t                   tls_ca_size;
+       char                    *tls_ca_file;
+       uint8_t                  tls_ca_optional;
        uint8_t                 *tls_cert;
        size_t                   tls_cert_len;
+       size_t                   tls_cert_size;
        char                    *tls_cert_file;
        char                     tls_ciphers[NAME_MAX];
        char                     tls_dhe_params[NAME_MAX];
        char                     tls_ecdhe_curve[NAME_MAX];
        uint8_t                 *tls_key;
        size_t                   tls_key_len;
+       size_t                   tls_key_size;
        char                    *tls_key_file;
        uint32_t                 tls_protocols;
 
@@ -465,8 +473,15 @@ TAILQ_HEAD(serverhosts, server_config);
 struct tls_config {
        uint32_t                 id;
 
+       in_port_t                port;
+       struct sockaddr_storage  ss;
+
+       int                      tls_ca_optional;
+       size_t                   tls_ca_len;
        size_t                   tls_cert_len;
        size_t                   tls_key_len;
+
+       size_t                   chunk_size;
 };
 
 struct server {
@@ -720,6 +735,7 @@ int  config_setserver(struct httpd *, st
 int     config_settls(struct httpd *, struct server *);
 int     config_getserver(struct httpd *, struct imsg *);
 int     config_gettls(struct httpd *, struct imsg *);
+int     config_gettls_chunk(struct httpd *, struct imsg *);
 int     config_setmedia(struct httpd *, struct media_type *);
 int     config_getmedia(struct httpd *, struct imsg *);
 int     config_setauth(struct httpd *, struct auth *);
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/parse.y,v
retrieving revision 1.77
diff -u -p -r1.77 parse.y
--- parse.y     22 Nov 2015 13:27:13 -0000      1.77
+++ parse.y     7 May 2016 02:45:39 -0000
@@ -129,12 +129,12 @@ typedef struct {
 
 %}
 
-%token ACCESS ALIAS AUTO BACKLOG BODY BUFFER CERTIFICATE CHROOT CIPHERS COMMON
-%token COMBINED CONNECTION DHE DIRECTORY ECDHE ERR FCGI INDEX IP KEY LISTEN
-%token LOCATION LOG LOGDIR MATCH MAXIMUM NO NODELAY ON PORT PREFORK PROTOCOLS
-%token REQUEST REQUESTS ROOT SACK SERVER SOCKET STRIP STYLE SYSLOG TCP TIMEOUT
-%token TLS TYPE TYPES HSTS MAXAGE SUBDOMAINS DEFAULT PRELOAD
-%token ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP RETURN PASS
+%token ACCESS ALIAS AUTO BACKLOG BODY BUFFER CA CERTIFICATE CHROOT CIPHERS
+%token COMMON COMBINED CONNECTION DHE DIRECTORY ECDHE ERR FCGI INDEX IP KEY
+%token LISTEN LOCATION LOG LOGDIR MATCH MAXIMUM NO NODELAY ON PORT PREFORK
+%token PROTOCOLS REQUEST REQUESTS ROOT SACK SERVER SOCKET STRIP STYLE SYSLOG
+%token TCP TIMEOUT TLS TYPE TYPES HSTS MAXAGE SUBDOMAINS DEFAULT PRELOAD
+%token ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP RETURN PASS OPTIONAL
 %token <v.string>      STRING
 %token  <v.number>     NUMBER
 %type  <v.port>        port
@@ -244,6 +244,7 @@ server              : SERVER optmatch STRING        {
                                s->srv_conf.flags |= SRVFLAG_SERVER_MATCH;
                        s->srv_conf.logformat = LOG_FORMAT_COMMON;
                        s->srv_conf.tls_protocols = TLS_PROTOCOLS_DEFAULT;
+                       s->srv_conf.tls_ca_file = NULL;
                        if ((s->srv_conf.tls_cert_file =
                            strdup(HTTPD_TLS_CERT)) == NULL)
                                fatal("out of memory");
@@ -315,7 +316,7 @@ server              : SERVER optmatch STRING        {
                        }
 
                        if (server_tls_load_keypair(srv) == -1) {
-                               yyerror("failed to load public/private keys "
+                               yyerror("XXfailed to load public/private keys "
                                    "for server %s", srv->srv_conf.name);
                                serverconfig_free(srv_conf);
                                free(srv);
@@ -663,7 +664,21 @@ tlsopts_l  : tlsopts optcommanl tlsopts_l
                | tlsopts optnl
                ;
 
-tlsopts                : CERTIFICATE STRING            {
+tlsopts                : CA STRING                     {
+                       srv_conf->tls_ca_optional = 0;
+                       free(srv_conf->tls_ca_file);
+                       if ((srv_conf->tls_ca_file = strdup($2)) == NULL)
+                               fatal("out of memory");
+                       free($2);
+               }
+               | CA STRING OPTIONAL            {
+                       srv_conf->tls_ca_optional = 1;
+                       free(srv_conf->tls_ca_file);
+                       if ((srv_conf->tls_ca_file = strdup($2)) == NULL)
+                               fatal("out of memory");
+                       free($2);
+               }
+               | CERTIFICATE STRING            {
                        free(srv_conf->tls_cert_file);
                        if ((srv_conf->tls_cert_file = strdup($2)) == NULL)
                                fatal("out of memory");
@@ -1148,6 +1163,7 @@ lookup(char *s)
                { "block",              BLOCK },
                { "body",               BODY },
                { "buffer",             BUFFER },
+               { "ca",                 CA},
                { "certificate",        CERTIFICATE },
                { "chroot",             CHROOT },
                { "ciphers",            CIPHERS },
@@ -1176,6 +1192,7 @@ lookup(char *s)
                { "no",                 NO },
                { "nodelay",            NODELAY },
                { "on",                 ON },
+               { "optional",           OPTIONAL },
                { "pass",               PASS },
                { "port",               PORT },
                { "prefork",            PREFORK },
@@ -1970,16 +1987,26 @@ server_inherit(struct server *src, struc
 
        /* Copy the source server and assign a new Id */
        memcpy(&dst->srv_conf, &src->srv_conf, sizeof(dst->srv_conf));
+       if (src->srv_conf.tls_ca_file != NULL) {
+               if ((dst->srv_conf.tls_ca_file =
+                   strdup(src->srv_conf.tls_ca_file)) == NULL)
+                       fatal("out of memory");
+       }
        if ((dst->srv_conf.tls_cert_file =
            strdup(src->srv_conf.tls_cert_file)) == NULL)
                fatal("out of memory");
        if ((dst->srv_conf.tls_key_file =
            strdup(src->srv_conf.tls_key_file)) == NULL)
                fatal("out of memory");
+       dst->srv_conf.tls_ca = NULL;
        dst->srv_conf.tls_cert = NULL;
        dst->srv_conf.tls_key = NULL;
+       dst->srv_conf.tls_ca_len = 0;
        dst->srv_conf.tls_cert_len = 0;
        dst->srv_conf.tls_key_len = 0;
+       dst->srv_conf.tls_ca_size = 0;
+       dst->srv_conf.tls_cert_size = 0;
+       dst->srv_conf.tls_key_size = 0;
 
        if (src->srv_conf.return_uri != NULL &&
            (dst->srv_conf.return_uri =
@@ -2012,7 +2039,7 @@ server_inherit(struct server *src, struc
        dst->srv_conf.flags |= (alias->flags & SRVFLAG_SERVER_MATCH);
 
        if (server_tls_load_keypair(dst) == -1) {
-               yyerror("failed to load public/private keys "
+               yyerror("YYfailed to load public/private keys "
                    "for server %s", dst->srv_conf.name);
                serverconfig_free(&dst->srv_conf);
                free(dst);
Index: server.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/server.c,v
retrieving revision 1.85
diff -u -p -r1.85 server.c
--- server.c    28 Apr 2016 17:18:06 -0000      1.85
+++ server.c    7 May 2016 22:58:20 -0000
@@ -138,6 +138,15 @@ server_tls_load_keypair(struct server *s
        if ((srv->srv_conf.flags & SRVFLAG_TLS) == 0)
                return (0);
 
+       if (srv->srv_conf.tls_ca_file != NULL) {
+               if ((srv->srv_conf.tls_ca = tls_load_file(
+                   srv->srv_conf.tls_ca_file, &srv->srv_conf.tls_ca_len,
+                   NULL)) == NULL)
+                       return (-1);
+               log_debug("%s: using certificate authority %s", __func__,
+                   srv->srv_conf.tls_ca_file);
+       }
+
        if ((srv->srv_conf.tls_cert = tls_load_file(
            srv->srv_conf.tls_cert_file, &srv->srv_conf.tls_cert_len,
            NULL)) == NULL)
@@ -199,6 +208,20 @@ server_tls_init(struct server *srv)
                return (-1);
        }
 
+       if (srv->srv_conf.tls_ca_len > 0) {
+               log_warnx("%s: set tls ca len: %zu", __func__,
+                   srv->srv_conf.tls_ca_len);
+               if (tls_config_set_ca_mem(srv->srv_tls_config,
+                   srv->srv_conf.tls_ca, srv->srv_conf.tls_ca_len) != 0) {
+                       log_warnx("%s: failed to set tls ca", __func__);
+                       return (-1);
+               }
+               if (srv->srv_conf.tls_ca_optional)
+                       tls_config_verify_client_optional(srv->srv_tls_config);
+               else
+                       tls_config_verify_client(srv->srv_tls_config);
+       }
+
        if (tls_config_set_keypair_mem(srv->srv_tls_config,
            srv->srv_conf.tls_cert, srv->srv_conf.tls_cert_len,
            srv->srv_conf.tls_key, srv->srv_conf.tls_key_len) != 0) {
@@ -215,12 +238,16 @@ server_tls_init(struct server *srv)
 
        /* We're now done with the public/private key... */
        tls_config_clear_keys(srv->srv_tls_config);
+       explicit_bzero(srv->srv_conf.tls_ca, srv->srv_conf.tls_ca_len);
        explicit_bzero(srv->srv_conf.tls_cert, srv->srv_conf.tls_cert_len);
        explicit_bzero(srv->srv_conf.tls_key, srv->srv_conf.tls_key_len);
+       free(srv->srv_conf.tls_ca);
        free(srv->srv_conf.tls_cert);
        free(srv->srv_conf.tls_key);
+       srv->srv_conf.tls_ca = NULL;
        srv->srv_conf.tls_cert = NULL;
        srv->srv_conf.tls_key = NULL;
+       srv->srv_conf.tls_ca_len = 0;
        srv->srv_conf.tls_cert_len = 0;
        srv->srv_conf.tls_key_len = 0;
 
@@ -317,9 +344,15 @@ void
 serverconfig_free(struct server_config *srv_conf)
 {
        free(srv_conf->return_uri);
+       free(srv_conf->tls_ca_file);
        free(srv_conf->tls_cert_file);
        free(srv_conf->tls_key_file);
 
+       if (srv_conf->tls_ca != NULL) {
+               explicit_bzero(srv_conf->tls_ca, srv_conf->tls_ca_len);
+               free(srv_conf->tls_ca);
+       }
+
        if (srv_conf->tls_cert != NULL) {
                explicit_bzero(srv_conf->tls_cert, srv_conf->tls_cert_len);
                free(srv_conf->tls_cert);
@@ -336,6 +369,8 @@ serverconfig_reset(struct server_config 
 {
        srv_conf->auth = NULL;
        srv_conf->return_uri = NULL;
+       srv_conf->tls_ca = NULL;
+       srv_conf->tls_ca_file = NULL;
        srv_conf->tls_cert = NULL;
        srv_conf->tls_cert_file = NULL;
        srv_conf->tls_key = NULL;
@@ -1132,6 +1167,9 @@ server_dispatch_parent(int fd, struct pr
                break;
        case IMSG_CFG_TLS:
                config_gettls(env, imsg);
+               break;
+       case IMSG_CFG_TLS_CHNK:
+               config_gettls_chunk(env, imsg);
                break;
        case IMSG_CFG_DONE:
                config_getcfg(env, imsg);
Index: tests/Client.pm
===================================================================
RCS file: /cvs/src/regress/usr.sbin/httpd/tests/Client.pm,v
retrieving revision 1.1
diff -u -p -r1.1 Client.pm
--- tests/Client.pm     16 Jul 2015 16:35:57 -0000      1.1
+++ tests/Client.pm     10 May 2016 16:09:23 -0000
@@ -59,6 +59,9 @@ sub child {
            PeerAddr            => $self->{connectaddr},
            PeerPort            => $self->{connectport},
            SSL_verify_mode     => SSL_VERIFY_NONE,
+           SSL_use_cert        => $self->{clientcert} ? 1 : 0,
+           SSL_cert_file       => $self->{clientcert} ? 
$self->{chroot}."/client.crt" : "",
+           SSL_key_file        => $self->{clientcert} ? 
$self->{chroot}."/client.key" : "",
        ) or die ref($self), " $iosocket socket connect failed: $!,$SSL_ERROR";
        print STDERR "connect sock: ",$cs->sockhost()," ",$cs->sockport(),"\n";
        print STDERR "connect peer: ",$cs->peerhost()," ",$cs->peerport(),"\n";
Index: tests/Httpd.pm
===================================================================
RCS file: /cvs/src/regress/usr.sbin/httpd/tests/Httpd.pm,v
retrieving revision 1.1
diff -u -p -r1.1 Httpd.pm
--- tests/Httpd.pm      16 Jul 2015 16:35:57 -0000      1.1
+++ tests/Httpd.pm      10 May 2016 16:03:01 -0000
@@ -71,6 +71,9 @@ sub new {
            print $fh "\n";
            print $fh "\ttls certificate \"".$args{chroot}."/server.crt\"\n";
            print $fh "\ttls key \"".$args{chroot}."/server.key\"";
+           if ($self->{clientcert}) {
+               print $fh "\n\ttls ca \"".$args{chroot}."/ca.crt\"";
+           }
        }
        print $fh "\n\troot \"/\"";
        print $fh "\n\tlog style combined";
Index: tests/Makefile
===================================================================
RCS file: /cvs/src/regress/usr.sbin/httpd/tests/Makefile,v
retrieving revision 1.2
diff -u -p -r1.2 Makefile
--- tests/Makefile      16 Jul 2015 17:00:41 -0000      1.2
+++ tests/Makefile      10 May 2016 14:18:13 -0000
@@ -88,7 +88,13 @@ server.req:
 server.crt: ca.crt server.req
        openssl x509 -CAcreateserial -CAkey ca.key -CA ca.crt -req -in 
server.req -out server.crt
 
-${REGRESS_TARGETS:M*tls*} ${REGRESS_TARGETS:M*https*}: server.crt
+client.req:
+       openssl req -batch -new -subj 
/L=OpenBSD/O=httpd-regress/OU=client/CN=user/ -nodes -newkey rsa -keyout 
client.key -out client.req
+
+client.crt: ca.crt client.req
+       openssl x509 -CAcreateserial -CAkey ca.key -CA ca.crt -req -in 
client.req -out client.crt
+
+${REGRESS_TARGETS:M*tls*} ${REGRESS_TARGETS:M*https*}: server.crt client.crt
 
 # make perl syntax check for all args files
 
Index: tests/args-tls.pl
===================================================================
RCS file: /cvs/src/regress/usr.sbin/httpd/tests/args-tls.pl,v
retrieving revision 1.1
diff -u -p -r1.1 args-tls.pl
--- tests/args-tls.pl   16 Jul 2015 16:35:57 -0000      1.1
+++ tests/args-tls.pl   10 May 2016 16:09:35 -0000
@@ -7,9 +7,11 @@ our %args = (
     client => {
        tls => 1,
        loggrep => 'Issuer.*/OU=ca/',
+       clientcert => 1,
     },
     httpd => {
        listentls => 1,
+       clientcert => 1,
     },
     len => 512,
     md5 => path_md5("512")

Reply via email to