ping. Tested with current source status.
On Tue, May 10, 2016 at 06:59:36PM +0200, Jan Klemkow wrote: > 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") >