From 91e68bd9c5582e4066a33f29126dd907a20a3308 Mon Sep 17 00:00:00 2001
From: "Thierry FOURNIER / OZON.IO" <thierry.fournier@ozon.io>
Date: Thu, 6 Oct 2016 10:56:48 +0200
Subject: [PATCH 3/5] BUG/MINOR: ssl: prevent multiple entries for the same
 certificate

Today, the certificate are indexed int he SNI tree using their CN and the
list of thier AltNames. So, Some certificates have the same names in the
CN and one of the AltNames entries.

Typically Let's Encrypt duplicate the the DNS name in the CN and the
AltName.

This patch prevent the creation of identical entries in the trees. It
checks the same DNS name and the same SSL context.

If the same certificate is registered two time it will be duplicated.

This patch should be backported in the 1.6 and 1.5 version.
---
 src/ssl_sock.c | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index f5b2fbc..9ff140d 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -1556,6 +1556,7 @@ static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, char *name,
 {
 	struct sni_ctx *sc;
 	int wild = 0, neg = 0;
+	struct ebmb_node *node;
 
 	if (*name == '!') {
 		neg = 1;
@@ -1571,12 +1572,27 @@ static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, char *name,
 	if (*name) {
 		int j, len;
 		len = strlen(name);
+		for (j = 0; j < len && j < trash.size; j++)
+			trash.str[j] = tolower(name[j]);
+		if (j >= trash.size)
+			return order;
+		trash.str[j] = 0;
+
+		/* Check for duplicates. */
+		if (wild)
+			node = ebst_lookup(&s->sni_w_ctx, trash.str);
+		else
+			node = ebst_lookup(&s->sni_ctx, trash.str);
+		for (; node; node = ebmb_next_dup(node)) {
+			sc = ebmb_entry(node, struct sni_ctx, name);
+			if (sc->ctx == ctx && sc->neg == neg)
+				return order;
+		}
+
 		sc = malloc(sizeof(struct sni_ctx) + len + 1);
 		if (!sc)
 			return order;
-		for (j = 0; j < len; j++)
-			sc->name.key[j] = tolower(name[j]);
-		sc->name.key[len] = 0;
+		memcpy(sc->name.key, trash.str, len + 1);
 		sc->ctx = ctx;
 		sc->order = order++;
 		sc->neg = neg;
-- 
2.9.5

