The following patch makes the TLS cipher list preference (server vs.
client) configurable in httpd (like in relayd):
Index: src/usr.sbin/httpd/config.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/config.c,v
retrieving revision 1.53
diff -u -p -u -r1.53 config.c
--- src/usr.sbin/httpd/config.c 19 Jul 2017 17:36:25 -0000 1.53
+++ src/usr.sbin/httpd/config.c 16 Aug 2017 12:40:59 -0000
@@ -472,6 +472,8 @@ config_getserver_config(struct httpd *en
srv_conf->hsts_max_age = parent->hsts_max_age;
srv_conf->hsts_flags = parent->hsts_flags;
+ srv_conf->tls_flags = parent->tls_flags;
+
memcpy(&srv_conf->timeout, &parent->timeout,
sizeof(srv_conf->timeout));
srv_conf->maxrequests = parent->maxrequests;
Index: src/usr.sbin/httpd/httpd.conf.5
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/httpd.conf.5,v
retrieving revision 1.84
diff -u -p -u -r1.84 httpd.conf.5
--- src/usr.sbin/httpd/httpd.conf.5 11 Aug 2017 20:30:45 -0000 1.84
+++ src/usr.sbin/httpd/httpd.conf.5 16 Aug 2017 12:40:59 -0000
@@ -518,6 +518,10 @@ The
should contain a PEM encoded certificate.
The default is
.Pa /etc/ssl/server.crt .
+.It Oo Ic no Oc Ic cipher-server-preference
+Prefer the server's cipher list over the client's preferences when
+choosing a cipher for the connection.
+This is enabled by default.
.It Ic ciphers Ar string
Specify the TLS cipher string.
If not specified, the default value
Index: src/usr.sbin/httpd/httpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/httpd.h,v
retrieving revision 1.134
diff -u -p -u -r1.134 httpd.h
--- src/usr.sbin/httpd/httpd.h 11 Aug 2017 18:48:56 -0000 1.134
+++ src/usr.sbin/httpd/httpd.h 16 Aug 2017 12:40:59 -0000
@@ -416,6 +416,8 @@ SPLAY_HEAD(client_tree, client);
"\10\01NODELAY\02NO_NODELAY\03SACK\04NO_SACK" \
"\05SOCKET_BUFFER_SIZE\06IP_TTL\07IP_MINTTL\10NO_SPLICE"
+#define TLSFLAG_CIPHER_SERVER_PREF 0x01
+
#define HSTSFLAG_SUBDOMAINS 0x01
#define HSTSFLAG_PRELOAD 0x02
#define HSTSFLAG_BITS "\10\01SUBDOMAINS\02PRELOAD"
@@ -514,6 +516,8 @@ struct server_config {
int hsts_max_age;
uint8_t hsts_flags;
+
+ uint8_t tls_flags;
TAILQ_ENTRY(server_config) entry;
};
Index: src/usr.sbin/httpd/parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/parse.y,v
retrieving revision 1.91
diff -u -p -u -r1.91 parse.y
--- src/usr.sbin/httpd/parse.y 11 Aug 2017 18:48:56 -0000 1.91
+++ src/usr.sbin/httpd/parse.y 16 Aug 2017 12:40:59 -0000
@@ -129,12 +129,13 @@ typedef struct {
%}
-%token ACCESS ALIAS AUTO BACKLOG BODY BUFFER CERTIFICATE CHROOT CIPHERS
COMMON
-%token COMBINED CONNECTION DHE DIRECTORY ECDHE ERR FCGI INDEX IP KEY
LIFETIME
-%token LISTEN LOCATION LOG LOGDIR MATCH MAXIMUM NO NODELAY OCSP ON PORT
PREFORK
-%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 ACCESS ALIAS AUTO BACKLOG BODY BUFFER CERTIFICATE CHROOT
CIPHERSRVPREF
+%token CIPHERS COMMON COMBINED CONNECTION DHE DIRECTORY ECDHE ERR FCGI
INDEX
+%token IP KEY LIFETIME LISTEN LOCATION LOG LOGDIR MATCH MAXIMUM NO NODELAY
+%token OCSP ON PORT PREFORK PROTOCOLS REQUESTS ROOT SACK SERVER SOCKET
STRIP
+%token STYLE SYSLOG TCP TICKET TIMEOUT TLS TYPE TYPES HSTS MAXAGE
SUBDOMAINS
+%token DEFAULT PRELOAD REQUEST ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP
+%token RETURN PASS
%token <v.string> STRING
%token <v.number> NUMBER
%type <v.port> port
@@ -260,6 +261,7 @@ server : SERVER optmatch STRING {
if ((s->srv_conf.tls_key_file =
strdup(HTTPD_TLS_KEY)) == NULL)
fatal("out of memory");
+ s->srv_conf.tls_flags = TLSFLAG_CIPHER_SERVER_PREF;
strlcpy(s->srv_conf.tls_ciphers,
HTTPD_TLS_CIPHERS,
sizeof(s->srv_conf.tls_ciphers));
@@ -727,6 +729,12 @@ tlsopts : CERTIFICATE STRING {
fatal("out of memory");
free($2);
}
+ | CIPHERSRVPREF {
+ srv_conf->tls_flags |= TLSFLAG_CIPHER_SERVER_PREF;
+ }
+ | NO CIPHERSRVPREF {
+ srv_conf->tls_flags &= ~TLSFLAG_CIPHER_SERVER_PREF;
+ }
| CIPHERS STRING {
if (strlcpy(srv_conf->tls_ciphers, $2,
sizeof(srv_conf->tls_ciphers)) >=
@@ -1219,6 +1227,7 @@ lookup(char *s)
{ "buffer", BUFFER },
{ "certificate", CERTIFICATE },
{ "chroot", CHROOT },
+ { "cipher-server-preference", CIPHERSRVPREF },
{ "ciphers", CIPHERS },
{ "combined", COMBINED },
{ "common", COMMON },
Index: src/usr.sbin/httpd/server.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/server.c,v
retrieving revision 1.111
diff -u -p -u -r1.111 server.c
--- src/usr.sbin/httpd/server.c 11 Aug 2017 18:48:56 -0000 1.111
+++ src/usr.sbin/httpd/server.c 16 Aug 2017 12:40:59 -0000
@@ -138,6 +138,8 @@ server_tls_cmp(struct server *s1, struct
return (-1);
if (sc1->tls_ticket_lifetime != sc2->tls_ticket_lifetime)
return (-1);
+ if (sc1->tls_flags != sc2->tls_flags)
+ return (-1);
if (strcmp(sc1->tls_ciphers, sc2->tls_ciphers) != 0)
return (-1);
if (strcmp(sc1->tls_dhe_params, sc2->tls_dhe_params) != 0)
@@ -225,6 +227,10 @@ server_tls_init(struct server *srv)
__func__, tls_config_error(srv->srv_tls_config));
return (-1);
}
+ if ((srv->srv_conf.tls_flags & TLSFLAG_CIPHER_SERVER_PREF) == 0)
+ tls_config_prefer_ciphers_client(srv->srv_tls_config);
+ else
+ tls_config_prefer_ciphers_server(srv->srv_tls_config);
if (tls_config_set_ciphers(srv->srv_tls_config,
srv->srv_conf.tls_ciphers) != 0) {
log_warnx("%s: failed to set tls ciphers: %s",