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",

Reply via email to