On Tue, 8 Aug 2017 15:10:36 +0930 Jack Burton <j...@saosce.com.au> wrote: > On Tue, 08 Aug 2017 14:23:02 +1000 > Joel Sing <j...@sing.id.au> wrote: > > On Saturday 29 July 2017 20:49:18 Jan Klemkow wrote: > > > In the End, I found and fixed the real bug here: > > > > > > @@ -430,7 +438,11 @@ config_getserver_config(struct httpd *en > > > } > > > > > > f = SRVFLAG_TLS; > > > - srv_conf->flags |= parent->flags & f; > > > + if ((srv_conf->flags & f) == 0) { > > > + srv_conf->flags |= parent->flags & f; > > > + srv_conf->tls_ca = parent->tls_ca; > > > + srv_conf->tls_crl = parent->tls_crl; > > > > I'd have to double check, however I'm pretty sure that this will > > result in a double-free since you're copying the pointer (without a > > reference count) across server config structs. Both will likely be > > passed to serverconfig_free(), which means free() will then be > > passed the same pointer twice. > > You're absolutely right. That happens when purging config on reload, > if the old config for a server doing tls client verify has two or more > location blocks... > > ...and my 30 July diff suffers from the same problem. <...> > Perhaps a better alternative would be to free the CA & CRL mem at the > end of server_tls_init() -- like we do already for the key pair -- > then add flags for CA & CRL use instead of just checking for null > pointers everywhere (as both my & Jan's diffs have been doing so far). > > It seems I have a couple of other changes to make too, so will roll > something like that in with them & post a revised diff later today or > tomorrow.
Okay, here's a further revised diff that takes the approach I proposed above to fixing the bug that Joel pointed out and also makes a few other small changes that were suggested to me off list: * the tls client ca directive now has an "optional" option (to request a client cert but not require it); * the extra bit string I got rid off a diff or two ago is back again, now passed through to fcgi as TLS_PEER_VERIFY (since there are now multiple possible modes of operation for tls client certs, so fcgi responders should have some way of knowing which are in use); * reworded the descriptions of the TLS_PEER_* fcgi vars in httpd.conf(5); and * fixed a minor typo in httpd.conf(5) that my earlier diff had introduced. Thoughts? Index: usr.sbin/httpd/config.c =================================================================== RCS file: /cvs/src/usr.sbin/httpd/config.c,v retrieving revision 1.53 diff -u -p -r1.53 config.c --- usr.sbin/httpd/config.c 19 Jul 2017 17:36:25 -0000 1.53 +++ usr.sbin/httpd/config.c 8 Aug 2017 12:36:19 -0000 @@ -304,10 +304,18 @@ config_setserver_tls(struct httpd *env, log_debug("%s: configuring tls for %s", __func__, srv_conf->name); + if (config_settls(env, srv, TLS_CFG_CA, "ca", srv_conf->tls_ca, + srv_conf->tls_ca_len) != 0) + return (-1); + if (config_settls(env, srv, TLS_CFG_CERT, "cert", srv_conf->tls_cert, srv_conf->tls_cert_len) != 0) return (-1); + if (config_settls(env, srv, TLS_CFG_CRL, "crl", srv_conf->tls_crl, + srv_conf->tls_crl_len) != 0) + return (-1); + if (config_settls(env, srv, TLS_CFG_KEY, "key", srv_conf->tls_key, srv_conf->tls_key_len) != 0) return (-1); @@ -431,6 +439,7 @@ config_getserver_config(struct httpd *en f = SRVFLAG_TLS; srv_conf->flags |= parent->flags & f; + srv_conf->tlsflags = parent->tlsflags; f = SRVFLAG_ACCESS_LOG; if ((srv_conf->flags & f) == 0) { @@ -655,9 +664,21 @@ config_getserver_tls(struct httpd *env, } switch (tls_conf.tls_type) { + case TLS_CFG_CA: + if (config_gettls(env, srv_conf, &tls_conf, "ca", p, len, + &srv_conf->tls_ca, &srv_conf->tls_ca_len) != 0) + goto fail; + break; + case TLS_CFG_CERT: if (config_gettls(env, srv_conf, &tls_conf, "cert", p, len, &srv_conf->tls_cert, &srv_conf->tls_cert_len) != 0) + goto fail; + break; + + case TLS_CFG_CRL: + if (config_gettls(env, srv_conf, &tls_conf, "crl", p, len, + &srv_conf->tls_crl, &srv_conf->tls_crl_len) != 0) goto fail; break; Index: usr.sbin/httpd/httpd.conf.5 =================================================================== RCS file: /cvs/src/usr.sbin/httpd/httpd.conf.5,v retrieving revision 1.82 diff -u -p -r1.82 httpd.conf.5 --- usr.sbin/httpd/httpd.conf.5 9 Apr 2017 09:13:28 -0000 1.82 +++ usr.sbin/httpd/httpd.conf.5 8 Aug 2017 12:36:19 -0000 @@ -342,7 +342,37 @@ The revision of the HTTP specification u .It Ic SERVER_SOFTWARE The server software name of .Xr httpd 8 . +.It Ic TLS_PEER_CHAIN +The TLS client certificate chain, PEM encoded, with newlines translated to +tabs. +.It Ic TLS_PEER_EXPIRES +The time at which the TLS client certificate expires, in seconds since the +epoch. +.It Ic TLS_PEER_HASH +A hash of the TLS client certificate. +See +.Xr tls_peer_cert_hash 3 . +.It Ic TLS_PEER_ISSUER +The issuer of the TLS client certificate. +.It Ic TLS_PEER_OCSP_URL +The OCSP URL from the TLS client certificate. +.It Ic TLS_PEER_SUBJECT +The subject of the TLS client certificate. +.It Ic TLS_PEER_VERIFY +A variable that is set to a comma separated list of TLS client verification +features in use. .El +.Pp +All +.Ic TLS_PEER_* +variables are omitted if TLS client verification is not in use. +All except +.Ic TLS_PEER_VERIFY +are also omitted if no TLS client certificate is offered when the +.Ic optional +argument to the +.Ic tls client ca +directive is in use. .It Ic hsts Oo Ar option Oc Enable HTTP Strict Transport Security. Valid options are: @@ -526,6 +556,23 @@ will be used (strong crypto cipher suite See the CIPHERS section of .Xr openssl 1 for information about SSL/TLS cipher suites and preference lists. +.It Ic client ca Ar cafile Oo Ic crl Ar crlfile Oc Op Ic optional +Require +.Po +or, if +.Ic optional +is specified, request but do not require +.Pc +TLS client certificates whose authenticity can be verified +against the CA certificate(s) in +.Ar cafile +in order to proceed beyond the TLS handshake. +With +.Ic crl +specified, additionally require that no certificate in the client chain be +listed as revoked in the CRL(s) in +.Ar crlfile . +CA certificates and CRLs should be PEM encoded. .It Ic dhe Ar params Specify the DHE parameters to use for DHE cipher suites. Valid parameter values are none, legacy and auto. @@ -688,6 +735,7 @@ server "www.example.com" { .Ed .Sh SEE ALSO .Xr htpasswd 1 , +.Xr tls_peer_cert_hash 3 , .Xr patterns 7 , .Xr httpd 8 , .Xr ocspcheck 8 , Index: usr.sbin/httpd/httpd.h =================================================================== RCS file: /cvs/src/usr.sbin/httpd/httpd.h,v retrieving revision 1.133 diff -u -p -r1.133 httpd.h --- usr.sbin/httpd/httpd.h 19 Jul 2017 17:36:25 -0000 1.133 +++ usr.sbin/httpd/httpd.h 8 Aug 2017 12:36:19 -0000 @@ -420,6 +420,11 @@ SPLAY_HEAD(client_tree, client); #define HSTSFLAG_PRELOAD 0x02 #define HSTSFLAG_BITS "\10\01SUBDOMAINS\02PRELOAD" +#define TLSFLAG_CA 0x01 +#define TLSFLAG_CRL 0x02 +#define TLSFLAG_OPTIONAL 0x04 +#define TLSFLAG_BITS "\10\01CA\02CRL\03OPTIONAL" + enum log_format { LOG_FORMAT_COMMON, LOG_FORMAT_COMBINED, @@ -476,9 +481,15 @@ struct server_config { uint32_t maxrequests; size_t maxrequestbody; + uint8_t *tls_ca; + char *tls_ca_file; + size_t tls_ca_len; uint8_t *tls_cert; size_t tls_cert_len; char *tls_cert_file; + uint8_t *tls_crl; + char *tls_crl_file; + size_t tls_crl_len; char tls_ciphers[NAME_MAX]; char tls_dhe_params[NAME_MAX]; char tls_ecdhe_curve[NAME_MAX]; @@ -491,6 +502,7 @@ struct server_config { char *tls_ocsp_staple_file; struct server_tls_ticket tls_ticket_key; int tls_ticket_lifetime; + uint8_t tlsflags; uint32_t flags; int strip; @@ -520,7 +532,9 @@ struct server_config { TAILQ_HEAD(serverhosts, server_config); enum tls_config_type { + TLS_CFG_CA, TLS_CFG_CERT, + TLS_CFG_CRL, TLS_CFG_KEY, TLS_CFG_OCSP_STAPLE, }; @@ -594,6 +608,8 @@ int cmdline_symset(char *); /* server.c */ void server(struct privsep *, struct privsep_proc *); int server_tls_cmp(struct server *, struct server *, int); +int server_tls_load_ca(struct server *); +int server_tls_load_crl(struct server *); int server_tls_load_keypair(struct server *); int server_tls_load_ocsp(struct server *); void server_generate_ticket_key(struct server_config *); Index: usr.sbin/httpd/parse.y =================================================================== RCS file: /cvs/src/usr.sbin/httpd/parse.y,v retrieving revision 1.90 diff -u -p -r1.90 parse.y --- usr.sbin/httpd/parse.y 25 Mar 2017 17:25:34 -0000 1.90 +++ usr.sbin/httpd/parse.y 8 Aug 2017 12:36:20 -0000 @@ -135,6 +135,7 @@ typedef struct { %token PROTOCOLS REQUESTS ROOT SACK SERVER SOCKET STRIP STYLE SYSLOG TCP TICKET %token TIMEOUT TLS TYPE TYPES HSTS MAXAGE SUBDOMAINS DEFAULT PRELOAD REQUEST %token ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP RETURN PASS +%token CA CLIENT CRL OPTIONAL %token <v.string> STRING %token <v.number> NUMBER %type <v.port> port @@ -344,6 +345,22 @@ server : SERVER optmatch STRING { YYERROR; } + if (server_tls_load_ca(srv) == -1) { + yyerror("server \"%s\": failed to load " + "ca cert(s)", srv->srv_conf.name); + serverconfig_free(srv_conf); + free(srv); + YYERROR; + } + + if (server_tls_load_crl(srv) == -1) { + yyerror("server \"%s\": failed to load crl(s)", + srv->srv_conf.name); + serverconfig_free(srv_conf); + free(srv); + YYERROR; + } + if (server_tls_load_ocsp(srv) == -1) { yyerror("server \"%s\": failed to load " "ocsp staple", srv->srv_conf.name); @@ -564,6 +581,7 @@ serveroptsl : LISTEN ON STRING opttls po sizeof(s->srv_conf.ss)); s->srv_conf.port = srv->srv_conf.port; s->srv_conf.prefixlen = srv->srv_conf.prefixlen; + s->srv_conf.tlsflags = srv->srv_conf.tlsflags; if (last_server_id == INT_MAX) { yyerror("too many servers/locations defined"); @@ -737,6 +755,13 @@ tlsopts : CERTIFICATE STRING { } free($2); } + | CLIENT CA STRING tlsclientopt { + srv_conf->tlsflags |= TLSFLAG_CA; + free(srv_conf->tls_ca_file); + if ((srv_conf->tls_ca_file = strdup($3)) == NULL) + fatal("out of memory"); + free($3); + } | DHE STRING { if (strlcpy(srv_conf->tls_dhe_params, $2, sizeof(srv_conf->tls_dhe_params)) >= @@ -785,6 +810,19 @@ tlsopts : CERTIFICATE STRING { } ; +tlsclientopt : /* empty */ + | tlsclientopt CRL STRING { + srv_conf->tlsflags |= TLSFLAG_CRL; + free(srv_conf->tls_crl_file); + if ((srv_conf->tls_crl_file = strdup($3)) == NULL) + fatal("out of memory"); + free($3); + } + | tlsclientopt OPTIONAL { + srv_conf->tlsflags |= TLSFLAG_OPTIONAL; + } + ; + root : ROOT rootflags | ROOT '{' optnl rootflags_l '}' ; @@ -1217,12 +1255,15 @@ lookup(char *s) { "block", BLOCK }, { "body", BODY }, { "buffer", BUFFER }, + { "ca", CA }, { "certificate", CERTIFICATE }, { "chroot", CHROOT }, { "ciphers", CIPHERS }, + { "client", CLIENT }, { "combined", COMBINED }, { "common", COMMON }, { "connection", CONNECTION }, + { "crl", CRL }, { "default", DEFAULT }, { "dhe", DHE }, { "directory", DIRECTORY }, @@ -1247,6 +1288,7 @@ lookup(char *s) { "nodelay", NODELAY }, { "ocsp", OCSP }, { "on", ON }, + { "optional", OPTIONAL }, { "pass", PASS }, { "port", PORT }, { "prefork", PREFORK }, @@ -2087,6 +2129,22 @@ server_inherit(struct server *src, struc if (server_tls_load_keypair(dst) == -1) { yyerror("failed to load public/private keys " + "for server %s", dst->srv_conf.name); + serverconfig_free(&dst->srv_conf); + free(dst); + return (NULL); + } + + if (server_tls_load_ca(dst) == -1) { + yyerror("failed to load ca cert(s) " + "for server %s", dst->srv_conf.name); + serverconfig_free(&dst->srv_conf); + free(dst); + return (NULL); + } + + if (server_tls_load_crl(dst) == -1) { + yyerror("failed to load crl(s) " "for server %s", dst->srv_conf.name); serverconfig_free(&dst->srv_conf); free(dst); Index: usr.sbin/httpd/server.c =================================================================== RCS file: /cvs/src/usr.sbin/httpd/server.c,v retrieving revision 1.110 diff -u -p -r1.110 server.c --- usr.sbin/httpd/server.c 19 Jul 2017 17:36:25 -0000 1.110 +++ usr.sbin/httpd/server.c 8 Aug 2017 12:36:20 -0000 @@ -134,6 +134,8 @@ server_tls_cmp(struct server *s1, struct sc1 = &s1->srv_conf; sc2 = &s2->srv_conf; + if (sc1->tlsflags != sc2->tlsflags) + return (-1); if (sc1->tls_protocols != sc2->tls_protocols) return (-1); if (sc1->tls_ticket_lifetime != sc2->tls_ticket_lifetime) @@ -197,6 +199,40 @@ server_tls_load_ocsp(struct server *srv) } int +server_tls_load_ca(struct server *srv) +{ + if ((srv->srv_conf.tlsflags & TLSFLAG_CA) == 0 || + srv->srv_conf.tls_ca_file == NULL) + return (0); + + 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 ca cert(s) from %s", __func__, + srv->srv_conf.tls_ca_file); + + return (0); +} + +int +server_tls_load_crl(struct server *srv) +{ + if ((srv->srv_conf.tlsflags & TLSFLAG_CRL) == 0 || + srv->srv_conf.tls_crl_file == NULL) + return (0); + + if ((srv->srv_conf.tls_crl = tls_load_file( + srv->srv_conf.tls_crl_file, + &srv->srv_conf.tls_crl_len, NULL)) == NULL) + return (-1); + log_debug("%s: using crl(s) from %s", __func__, + srv->srv_conf.tls_crl_file); + + return (0); +} + +int server_tls_init(struct server *srv) { struct server_config *srv_conf; @@ -254,6 +290,27 @@ server_tls_init(struct server *srv) return (-1); } + if (srv->srv_conf.tls_ca != NULL) { + 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 add ca cert(s)", __func__); + return (-1); + } + if (srv->srv_conf.tlsflags & TLSFLAG_OPTIONAL) + tls_config_verify_client_optional(srv->srv_tls_config); + else + tls_config_verify_client(srv->srv_tls_config); + + if (srv->srv_conf.tls_crl != NULL) { + if (tls_config_set_crl_mem(srv->srv_tls_config, + srv->srv_conf.tls_crl, + srv->srv_conf.tls_crl_len) != 0) { + log_warnx("%s: failed to add crl(s)", __func__); + return (-1); + } + } + } + TAILQ_FOREACH(srv_conf, &srv->srv_hosts, entry) { if (srv_conf->tls_cert == NULL || srv_conf->tls_key == NULL) continue; @@ -267,6 +324,28 @@ server_tls_init(struct server *srv) log_warnx("%s: failed to add tls keypair", __func__); return (-1); } + + if (srv->srv_conf.tls_ca == NULL) + continue; + + log_debug("%s: adding ca cert(s) for server %s", __func__, + srv->srv_conf.name); + if (tls_config_set_ca_mem(srv->srv_tls_config, + srv_conf->tls_ca, srv_conf->tls_ca_len) != 0) { + log_warnx("%s: failed to add ca cert(s)", __func__); + return (-1); + } + + if (srv->srv_conf.tls_crl == NULL) + continue; + + log_debug("%s: adding crl(s) for server %s", __func__, + srv->srv_conf.name); + if (tls_config_set_crl_mem(srv->srv_tls_config, + srv_conf->tls_crl, srv_conf->tls_crl_len) != 0) { + log_warnx("%s: failed to add crl(s)", __func__); + return (-1); + } } /* set common session ID among all processes */ @@ -300,13 +379,19 @@ server_tls_init(struct server *srv) return (-1); } - /* We're now done with the public/private key... */ + /* We're now done with the public/private key & ca/crl... */ tls_config_clear_keys(srv->srv_tls_config); freezero(srv->srv_conf.tls_cert, srv->srv_conf.tls_cert_len); freezero(srv->srv_conf.tls_key, srv->srv_conf.tls_key_len); + free(srv->srv_conf.tls_ca); + free(srv->srv_conf.tls_crl); + srv->srv_conf.tls_ca = NULL; srv->srv_conf.tls_cert = NULL; + srv->srv_conf.tls_crl = 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_crl_len = 0; srv->srv_conf.tls_key_len = 0; return (0); @@ -412,7 +497,11 @@ void serverconfig_free(struct server_config *srv_conf) { free(srv_conf->return_uri); + free(srv_conf->tls_ca_file); + free(srv_conf->tls_ca); free(srv_conf->tls_cert_file); + free(srv_conf->tls_crl_file); + free(srv_conf->tls_crl); free(srv_conf->tls_key_file); free(srv_conf->tls_ocsp_staple_file); free(srv_conf->tls_ocsp_staple); @@ -425,8 +514,12 @@ 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_crl = NULL; + srv_conf->tls_crl_file = NULL; srv_conf->tls_key = NULL; srv_conf->tls_key_file = NULL; srv_conf->tls_ocsp_staple = NULL; Index: usr.sbin/httpd/server_fcgi.c =================================================================== RCS file: /cvs/src/usr.sbin/httpd/server_fcgi.c,v retrieving revision 1.75 diff -u -p -r1.75 server_fcgi.c --- usr.sbin/httpd/server_fcgi.c 31 Jul 2017 08:02:49 -0000 1.75 +++ usr.sbin/httpd/server_fcgi.c 8 Aug 2017 12:36:20 -0000 @@ -93,11 +93,12 @@ server_fcgi(struct httpd *env, struct cl struct fcgi_record_header *h; struct fcgi_begin_request_body *begin; char hbuf[HOST_NAME_MAX+1]; - size_t scriptlen; + size_t chainlen, scriptlen; int pathlen; int fd = -1, ret; const char *stripped, *p, *alias, *errstr = NULL; - char *str, *script = NULL; + char *chainc, *chainp, *str, *script = NULL; + const uint8_t *chain; if (srv_conf->socket[0] == ':') { struct sockaddr_storage ss; @@ -282,11 +283,58 @@ server_fcgi(struct httpd *env, struct cl goto fail; } - if (srv_conf->flags & SRVFLAG_TLS) + if (srv_conf->flags & SRVFLAG_TLS) { if (fcgi_add_param(¶m, "HTTPS", "on", clt) == -1) { errstr = "failed to encode param"; goto fail; } + if ((srv_conf->tlsflags & TLSFLAG_CA) && + (chain = tls_peer_cert_chain_pem(clt->clt_tls_ctx, + &chainlen)) != NULL) { + if ((chainc = strndup(chain, chainlen)) == NULL) + goto fail; + chainp = chainc; + while ((chainp = strchr(chainp, '\n')) != NULL) + *chainp = '\t'; + ret = fcgi_add_param(¶m, "TLS_PEER_CHAIN", chainc, + clt); + free(chainc); + if (ret == -1) { + errstr = "failed to encode param"; + goto fail; + } + if (fcgi_add_param(¶m, "TLS_PEER_SUBJECT", + tls_peer_cert_subject(clt->clt_tls_ctx), clt) == -1 + || fcgi_add_param(¶m, "TLS_PEER_ISSUER", + tls_peer_cert_issuer(clt->clt_tls_ctx), clt) == -1 + || fcgi_add_param(¶m, "TLS_PEER_HASH", + tls_peer_cert_hash(clt->clt_tls_ctx), clt) == -1) { + errstr = "failed to encode param"; + goto fail; + } + if (asprintf(&str, "%lld", + tls_peer_cert_notafter(clt->clt_tls_ctx)) == -1 + || fcgi_add_param(¶m, "TLS_PEER_EXPIRES", str, + clt) == -1) { + errstr = "failed to encode param"; + goto fail; + } + free(str); + str = NULL; + if (tls_peer_ocsp_url(clt->clt_tls_ctx) != NULL + && fcgi_add_param(¶m, "TLS_PEER_OCSP_URL", + tls_peer_ocsp_url(clt->clt_tls_ctx), clt) == -1) { + errstr = "failed to encode param"; + goto fail; + } + } + if (srv_conf->tlsflags != 0 && fcgi_add_param(¶m, + "TLS_PEER_VERIFY", printb_flags(srv_conf->tlsflags, + TLSFLAG_BITS), clt) == -1) { + errstr = "failed to encode param"; + goto fail; + } + } (void)print_host(&clt->clt_ss, hbuf, sizeof(hbuf)); if (fcgi_add_param(¶m, "REMOTE_ADDR", hbuf, clt) == -1) { Index: regress/usr.sbin/httpd/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 --- regress/usr.sbin/httpd/tests/Client.pm 16 Jul 2015 16:35:57 -0000 1.1 +++ regress/usr.sbin/httpd/tests/Client.pm 8 Aug 2017 12:36:20 -0000 @@ -59,6 +59,11 @@ sub child { PeerAddr => $self->{connectaddr}, PeerPort => $self->{connectport}, SSL_verify_mode => SSL_VERIFY_NONE, + SSL_use_cert => $self->{offertlscert} ? 1 : 0, + SSL_cert_file => $self->{offertlscert} ? + $self->{chroot}."/client.crt" : "", + SSL_key_file => $self->{offertlscert} ? + $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: regress/usr.sbin/httpd/tests/Httpd.pm =================================================================== RCS file: /cvs/src/regress/usr.sbin/httpd/tests/Httpd.pm,v retrieving revision 1.2 diff -u -p -r1.2 Httpd.pm --- regress/usr.sbin/httpd/tests/Httpd.pm 30 Jan 2017 21:18:24 -0000 1.2 +++ regress/usr.sbin/httpd/tests/Httpd.pm 8 Aug 2017 12:36:20 -0000 @@ -72,6 +72,8 @@ sub new { print $fh "\n"; print $fh "\ttls certificate \"".$args{chroot}."/server.crt\"\n"; print $fh "\ttls key \"".$args{chroot}."/server.key\""; + $self->{verifytls} + and print $fh "\ntls client ca \"".$args{chroot}."/ca.crt\""; } print $fh "\n\troot \"/\""; print $fh "\n\tlog style combined"; Index: regress/usr.sbin/httpd/tests/Makefile =================================================================== RCS file: /cvs/src/regress/usr.sbin/httpd/tests/Makefile,v retrieving revision 1.8 diff -u -p -r1.8 Makefile --- regress/usr.sbin/httpd/tests/Makefile 14 Jul 2017 13:31:44 -0000 1.8 +++ regress/usr.sbin/httpd/tests/Makefile 8 Aug 2017 12:36:20 -0000 @@ -77,10 +77,16 @@ ca.crt: server.req: openssl req -batch -new -subj /L=OpenBSD/O=httpd-regress/OU=server/CN=localhost/ -nodes -newkey rsa -keyout server.key -out server.req +client.req: + openssl req -batch -new -subj /L=OpenBSD/O=httpd-regress/OU=client/CN=localhost/ -nodes -newkey rsa -keyout client.key -out $@ + 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.crt: ca.crt client.req + openssl x509 -CAcreateserial -CAkey ca.key -CA ca.crt -req -in client.req -out $@ + +${REGRESS_TARGETS:M*tls*} ${REGRESS_TARGETS:M*https*}: server.crt client.crt # make perl syntax check for all args files Index: regress/usr.sbin/httpd/tests/args-tls-verify.pl =================================================================== RCS file: regress/usr.sbin/httpd/tests/args-tls-verify.pl diff -N regress/usr.sbin/httpd/tests/args-tls-verify.pl --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ regress/usr.sbin/httpd/tests/args-tls-verify.pl 8 Aug 2017 12:36:20 -0000 @@ -0,0 +1,20 @@ +# test https connection, verifying client cert + +use strict; +use warnings; + +our %args = ( + client => { + tls => 1, + offertlscert => 1, + loggrep => 'Issuer.*/OU=ca/', + }, + httpd => { + listentls => 1, + verifytls => 1, + }, + len => 512, + md5 => path_md5("512") +); + +1;