]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: ssl: add bind-option "strict-sni"
authorEmmanuel Hocdet <manu@gandi.net>
Thu, 24 Jan 2013 16:17:15 +0000 (17:17 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 24 Jan 2013 16:23:33 +0000 (17:23 +0100)
This new option ensures that there is no possible fallback to a default
certificate if the client does not provide an SNI which is explicitly
handled by a certificate.

doc/configuration.txt
include/types/listener.h
src/ssl_sock.c

index c88592a720dcd4b5fd8cac3bd45da81da613b5b3..30647a982f3d33c2baba89fbb200da2306469033 100644 (file)
@@ -7241,6 +7241,12 @@ ssl
   appear in clear text, so that ACLs and HTTP processing will only have access
   to deciphered contents.
 
+strict-sni
+  This setting is only available when support for OpenSSL was built in. The
+  SSL/TLS negotiation is allow only if the client provided an SNI which match
+  a certificate. The default certificate is not used.
+  See the "crt" option for more information.
+
 tfo
   Is an optional keyword which is supported only on Linux kernels >= 3.6. It
   enables TCP Fast Open on the listening socket, which means that clients which
index d5d91f43f8722875fc16943732f6c89e9e605f0b..2f584e3f297556935db07d71617b1e66e79de9d6 100644 (file)
@@ -127,6 +127,7 @@ struct bind_conf {
        SSL_CTX *default_ctx;      /* SSL context of first/default certificate */
        char *npn_str;             /* NPN protocol string */
        int npn_len;               /* NPN protocol string length */
+       int strict_sni;            /* refuse negotiation if sni doesn't match a certificate */
        struct eb_root sni_ctx;    /* sni_ctx tree of all known certs full-names sorted by name */
        struct eb_root sni_w_ctx;  /* sni_ctx tree of all known certs wildcards sorted by name */
 #endif
index 87eff2b7c41aba1c71baba1a6ed55f82b1b16d12..f814276064fbb29cb5e4566091e8d00de39b3665 100644 (file)
@@ -178,8 +178,12 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, struct bind_conf *s)
        (void)al; /* shut gcc stupid warning */
 
        servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
-       if (!servername)
-               return SSL_TLSEXT_ERR_NOACK;
+       if (!servername) {
+               if (s->strict_sni)
+                       return SSL_TLSEXT_ERR_ALERT_FATAL;
+               else
+                       return SSL_TLSEXT_ERR_NOACK;
+       }
 
        for (i = 0; i < trash.size; i++) {
                if (!servername[i])
@@ -193,13 +197,20 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, struct bind_conf *s)
        /* lookup in full qualified names */
        node = ebst_lookup(&s->sni_ctx, trash.str);
        if (!node) {
-               if (!wildp)
-                       return SSL_TLSEXT_ERR_ALERT_WARNING;
-
+               if (!wildp) {
+                       if (s->strict_sni)
+                               return SSL_TLSEXT_ERR_ALERT_FATAL;
+                       else
+                               return SSL_TLSEXT_ERR_ALERT_WARNING;
+               }
                /* lookup in full wildcards names */
                node = ebst_lookup(&s->sni_w_ctx, wildp);
-               if (!node)
-                       return SSL_TLSEXT_ERR_ALERT_WARNING;
+               if (!node) {
+                       if (s->strict_sni)
+                               return SSL_TLSEXT_ERR_ALERT_FATAL;
+                       else
+                               return SSL_TLSEXT_ERR_ALERT_WARNING;
+               }
        }
 
        /* switch ctx */
@@ -2569,6 +2580,13 @@ static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bin
        return 0;
 }
 
+/* parse the "strict-sni" bind keyword */
+static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
+{
+       conf->strict_sni = 1;
+       return 0;
+}
+
 /* parse the "verify" bind keyword */
 static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
 {
@@ -2888,6 +2906,7 @@ static struct bind_kw_list bind_kws = { "SSL", { }, {
        { "no-tlsv12",             bind_parse_no_tlsv12,      0 }, /* disable TLSv12 */
        { "no-tls-tickets",        bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
        { "ssl",                   bind_parse_ssl,            0 }, /* enable SSL processing */
+       { "strict-sni",            bind_parse_strict_sni,     0 }, /* refuse negotiation if sni doesn't match a certificate */
        { "verify",                bind_parse_verify,         1 }, /* set SSL verify method */
        { "npn",                   bind_parse_npn,            1 }, /* set NPN supported protocols */
        { NULL, NULL, 0 },