Download raw body.
httpd: support encrypted tls server keys
Hello,
this diff enables using encrypted tls server keys with httpd.
The heavy lifting is already done in tls_load_file(3). I'm only passing the
needed password and added the config settings plus a regression test.
The additions to the man page are, with the exception of the additional
word 'optional', the same as in the relayd man page.
Jan
diff --git usr.sbin/httpd/httpd.h usr.sbin/httpd/httpd.h
index baf11d1b523..71fd829be6b 100644
--- usr.sbin/httpd/httpd.h
+++ usr.sbin/httpd/httpd.h
@@ -61,6 +61,7 @@
#define HTTPD_LOGVIS VIS_NL|VIS_TAB|VIS_CSTYLE
#define HTTPD_TLS_CERT "/etc/ssl/server.crt"
#define HTTPD_TLS_KEY "/etc/ssl/private/server.key"
+#define HTTPD_TLS_KEY_PASS NULL
#define HTTPD_TLS_CONFIG_MAX 511
#define HTTPD_TLS_CIPHERS "compat"
#define HTTPD_TLS_DHE_PARAMS "none"
@@ -508,6 +509,7 @@ struct server_config {
uint8_t *tls_key;
size_t tls_key_len;
char *tls_key_file;
+ char *tls_key_pass;
uint32_t tls_protocols;
uint8_t *tls_ocsp_staple;
size_t tls_ocsp_staple_len;
diff --git usr.sbin/httpd/parse.y usr.sbin/httpd/parse.y
index 326b249662f..856f95dbf95 100644
--- usr.sbin/httpd/parse.y
+++ usr.sbin/httpd/parse.y
@@ -141,7 +141,7 @@ typedef struct {
%token TIMEOUT TLS TYPE TYPES HSTS MAXAGE SUBDOMAINS DEFAULT PRELOAD
REQUEST
%token ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP RETURN PASS REWRITE
%token CA CLIENT CRL OPTIONAL PARAM FORWARDED FOUND NOT
-%token ERRDOCS GZIPSTATIC BANNER
+%token ERRDOCS GZIPSTATIC BANNER PASSWORD
%token <v.string> STRING
%token <v.number> NUMBER
%type <v.port> port
@@ -870,7 +870,7 @@ tlsopts : CERTIFICATE STRING {
fatal("out of memory");
free($2);
}
- | KEY STRING {
+ | KEY STRING tlskeyopt {
free(srv_conf->tls_key_file);
if ((srv_conf->tls_key_file = strdup($2)) == NULL)
fatal("out of memory");
@@ -947,7 +947,14 @@ tlsopts : CERTIFICATE STRING {
srv_conf->tls_ticket_lifetime = 0;
}
;
-
+tlskeyopt :
+ | tlskeyopt PASSWORD STRING {
+ free(srv_conf->tls_key_pass);
+ if ((srv_conf->tls_key_pass = strdup($3)) == NULL)
+ fatal("out of memory");
+ free($3);
+ }
+ ;
tlsclientopt : /* empty */
| tlsclientopt CRL STRING {
srv_conf->tls_flags = TLSFLAG_CRL;
@@ -1496,6 +1503,7 @@ lookup(char *s)
{ "optional", OPTIONAL },
{ "param", PARAM },
{ "pass", PASS },
+ { "password", PASSWORD },
{ "port", PORT },
{ "prefork", PREFORK },
{ "preload", PRELOAD },
diff --git usr.sbin/httpd/server.c usr.sbin/httpd/server.c
index a38cf018d81..3bc22a62f6a 100644
--- usr.sbin/httpd/server.c
+++ usr.sbin/httpd/server.c
@@ -162,9 +162,8 @@ server_tls_load_keypair(struct server *srv)
log_debug("%s: using certificate %s", __func__,
srv->srv_conf.tls_cert_file);
- /* XXX allow to specify password for encrypted key */
if ((srv->srv_conf.tls_key =
tls_load_file(srv->srv_conf.tls_key_file,
- &srv->srv_conf.tls_key_len, NULL)) == NULL)
+ &srv->srv_conf.tls_key_len, srv->srv_conf.tls_key_pass)) ==
NULL)
return (-1);
log_debug("%s: using private key %s", __func__,
srv->srv_conf.tls_key_file);
diff --git regress/usr.sbin/httpd/tests/Httpd.pm
regress/usr.sbin/httpd/tests/Httpd.pm
index 53fed72040c..66f5cb7ba73 100644
--- regress/usr.sbin/httpd/tests/Httpd.pm
+++ regress/usr.sbin/httpd/tests/Httpd.pm
@@ -71,7 +71,12 @@ sub new {
if ($self->{listentls}) {
print $fh "\n";
print $fh "\ttls certificate
\"".$args{chroot}."/server.crt\"\n";
- print $fh "\ttls key \"".$args{chroot}."/server.key\"";
+ my $tlskey = "\ttls key \"".$args{chroot};
+ if ($self->{tlskeypw}) {
+ print $fh ${tlskey}."/server.enc.key\" password
\"password1\"";
+ } else {
+ print $fh ${tlskey}."/server.key\"";
+ }
$self->{verifytls}
and print $fh "\n\ttls client ca
\"".$args{chroot}."/ca.crt\"";
}
diff --git regress/usr.sbin/httpd/tests/Makefile
regress/usr.sbin/httpd/tests/Makefile
index 3afb588ce93..f1981257cdf 100644
--- regress/usr.sbin/httpd/tests/Makefile
+++ regress/usr.sbin/httpd/tests/Makefile
@@ -82,7 +82,11 @@ server.crt: ca.crt server.req
client.crt: ca.crt client.req
openssl x509 -CAcreateserial -CAkey ca.key -CA ca.crt -req -in
client.req -out $@
+server_enc.key:
+ openssl pkcs8 -topk8 -in server.key -out server.enc.key -passout
pass:password1
+
${REGRESS_TARGETS:M*tls*} ${REGRESS_TARGETS:M*https*}: server.crt
client.crt
+${REGRESS_TARGETS:M*tls-pw*} ${REGRESS_TARGETS:M*https*}: server.crt
client.crt server_enc.key
# make perl syntax check for all args files
diff --git regress/usr.sbin/httpd/tests/args-tls-pw.pl
regress/usr.sbin/httpd/tests/args-tls-pw.pl
new file mode 100644
index 00000000000..f5d512d726e
--- /dev/null
+++ regress/usr.sbin/httpd/tests/args-tls-pw.pl
@@ -0,0 +1,19 @@
+# test https connection
+
+use strict;
+use warnings;
+
+our %args = (
+ client => {
+ tls => 1,
+ loggrep => 'Issuer.*/OU=ca/',
+ },
+ httpd => {
+ listentls => 1,
+ tlskeypw => 1,
+ },
+ len => 512,
+ md5 => path_md5("512")
+);
+
+1;
diff --git usr.sbin/httpd/httpd.conf.5 usr.sbin/httpd/httpd.conf.5
index 3053709a359..745f7573bf6 100644
--- usr.sbin/httpd/httpd.conf.5
+++ usr.sbin/httpd/httpd.conf.5
@@ -709,7 +709,7 @@ in order of preference.
The special value of "default" will use the default curves; see
.Xr tls_config_set_ecdhecurves 3
for further details.
-.It Ic key Ar file
+.It Ic key Ar file Ic password Ar password
Specify the private key to use for this server.
The
.Ar file
@@ -719,6 +719,9 @@ root directory of
.Nm httpd .
The default is
.Pa /etc/ssl/private/server.key .
+The optional
+.Ar password
+argument will specify the password to decrypt the key.
.It Ic ocsp Ar file
Specify an OCSP response to be stapled during TLS handshakes
with this server.
httpd: support encrypted tls server keys