shithub: tlssrv.sni

Download patch

ref: a8a35ee8f3dd514407206a3b09578bb66f06f097
parent: 1f4e0bdb4084f1e56282f2bf6c55170de12aec23
author: igor <igor@mux>
date: Thu Jan 25 05:41:10 EST 2024

Merge tlshand.c from front adding TLS renegotiation capability.

--- a/tlshand.c
+++ b/tlshand.c
@@ -68,6 +68,7 @@
 	uchar sec[MasterSecretSize];	// master secret
 	uchar srandom[RandomSize];	// server random
 	uchar crandom[RandomSize];	// client random
+	int reneg;			// secure renegotiation flag
 
 	Namedcurve *nc; // selected curve for ECDHE
 	// diffie hellman state
@@ -253,6 +254,7 @@
 	TLS_PSK_WITH_AES_128_CBC_SHA		= 0x008C,
 
 	TLS_FALLBACK_SCSV = 0x5600,
+	TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF,
 };
 
 // compression methods
@@ -273,6 +275,7 @@
 	Extec = 0x000a,
 	Extecp = 0x000b,
 	Extsigalgs = 0x000d,
+	Extreneg = 0xff01,
 };
 
 static Algs cipherAlgs[] = {
@@ -429,7 +432,7 @@
 tlsServer(int fd, TLSconn *conn)
 {
 	char buf[8];
-	char dname[64];
+	char dname[32];
 	uchar seed[2*RandomSize];
 	int n, data, ctl, hand;
 	TlsConnection *tls;
@@ -436,7 +439,7 @@
 
 	if(conn == nil)
 		return -1;
-	ctl = open("#a/tls/clone", ORDWR|OCEXEC);
+	ctl = open("/net/tls/clone", ORDWR|OCEXEC);
 	if(ctl < 0)
 		return -1;
 	n = read(ctl, buf, sizeof(buf)-1);
@@ -445,8 +448,8 @@
 		return -1;
 	}
 	buf[n] = 0;
-	snprint(conn->dir, sizeof(conn->dir), "#a/tls/%s", buf);
-	snprint(dname, sizeof(dname), "#a/tls/%s/hand", buf);
+	snprint(conn->dir, sizeof(conn->dir), "/net/tls/%s", buf);
+	snprint(dname, sizeof(dname), "/net/tls/%s/hand", buf);
 	hand = open(dname, ORDWR|OCEXEC);
 	if(hand < 0){
 		close(ctl);
@@ -459,7 +462,7 @@
 		conn->pskID, conn->psk, conn->psklen,
 		conn->trace, conn->chain);
 	if(tls != nil){
-		snprint(dname, sizeof(dname), "#a/tls/%s/data", buf);
+		snprint(dname, sizeof(dname), "/net/tls/%s/data", buf);
 		data = open(dname, ORDWR);
 	}
 	close(hand);
@@ -562,7 +565,7 @@
 tlsClient(int fd, TLSconn *conn)
 {
 	char buf[8];
-	char dname[64];
+	char dname[32];
 	uchar seed[2*RandomSize];
 	int n, data, ctl, hand;
 	TlsConnection *tls;
@@ -570,7 +573,7 @@
 
 	if(conn == nil)
 		return -1;
-	ctl = open("#a/tls/clone", ORDWR|OCEXEC);
+	ctl = open("/net/tls/clone", ORDWR|OCEXEC);
 	if(ctl < 0)
 		return -1;
 	n = read(ctl, buf, sizeof(buf)-1);
@@ -579,14 +582,14 @@
 		return -1;
 	}
 	buf[n] = 0;
-	snprint(conn->dir, sizeof(conn->dir), "#a/tls/%s", buf);
-	snprint(dname, sizeof(dname), "#a/tls/%s/hand", buf);
+	snprint(conn->dir, sizeof(conn->dir), "/net/tls/%s", buf);
+	snprint(dname, sizeof(dname), "/net/tls/%s/hand", buf);
 	hand = open(dname, ORDWR|OCEXEC);
 	if(hand < 0){
 		close(ctl);
 		return -1;
 	}
-	snprint(dname, sizeof(dname), "#a/tls/%s/data", buf);
+	snprint(dname, sizeof(dname), "/net/tls/%s/data", buf);
 	data = open(dname, ORDWR);
 	if(data < 0){
 		close(hand);
@@ -686,6 +689,16 @@
 						break;
 					}
 			break;
+		case Extreneg:
+			if(n < 1 || *p != (n -= 1))
+				goto Short;
+			if(*p != 0){
+				tlsError(c, EHandshakeFailure, "invalid renegotiation extension");
+				return -1;
+			}
+			c->sec->reneg = 1;
+			p++;
+
 		}
 	}
 
@@ -695,6 +708,29 @@
 	return -1; 
 } 
 
+static uchar*
+tlsServerExtensions(TlsConnection *c, int *plen)
+{
+	uchar *b, *p;
+	int m;
+
+	p = b = nil;
+
+	// RFC5746 - Renegotiation Indication
+	if(c->sec->reneg){
+		m = p - b;
+		b = erealloc(b, m + 2+2+1);
+		p = b + m;
+
+		put16(p, Extreneg), p += 2;	/* Type: renegotiation_info */
+		put16(p, 1), p += 2;		/* Length */
+		*p++ = 0;			/* Renegotiated Connection Length */
+	}
+
+	*plen = p - b;
+	return b;
+}
+
 static TlsConnection *
 tlsServer2(int ctl, int hand,
 	uchar **cert, int certlen,
@@ -701,7 +737,8 @@
 	char *pskid, uchar *psk, int psklen,
 	int (*trace)(char*fmt, ...), PEMChain *chp)
 {
-	int cipher, compressor, numcerts, i;
+	int cipher, compressor, numcerts, i, extlen;
+	uchar *ext;
 	TlsConnection *c;
 	Msg m;
 
@@ -774,6 +811,8 @@
 			goto Err;
 		}
 	}
+	if(lookupid(m.u.clientHello.ciphers, TLS_EMPTY_RENEGOTIATION_INFO_SCSV) >= 0)
+		c->sec->reneg = 1;
 	cipher = okCipher(m.u.clientHello.ciphers, psklen > 0, c->sec->nc != nil);
 	if(cipher < 0 || !setAlgs(c, cipher)) {
 		tlsError(c, EHandshakeFailure, "no matching cipher suite");
@@ -794,6 +833,9 @@
 	m.u.serverHello.cipher = cipher;
 	m.u.serverHello.compressor = compressor;
 	m.u.serverHello.sid = makebytes(nil, 0);
+	ext = tlsServerExtensions(c, &extlen);
+	m.u.serverHello.extensions = makebytes(ext, extlen);
+	free(ext);
 	if(!msgSend(c, &m, AQueue))
 		goto Err;
 
@@ -2241,15 +2283,15 @@
 		unlock(&ciphLock);
 		return nciphers;
 	}
-	j = open("#a/tls/encalgs", OREAD|OCEXEC);
+	j = open("/net/tls/encalgs", OREAD|OCEXEC);
 	if(j < 0){
-		werrstr("can't open #a/tls/encalgs: %r");
+		werrstr("can't open /net/tls/encalgs: %r");
 		goto out;
 	}
 	n = read(j, s, MaxAlgF-1);
 	close(j);
 	if(n <= 0){
-		werrstr("nothing in #a/tls/encalgs: %r");
+		werrstr("nothing in /net/tls/encalgs: %r");
 		goto out;
 	}
 	s[n] = 0;
@@ -2265,15 +2307,15 @@
 		cipherAlgs[i].ok = ok;
 	}
 
-	j = open("#a/tls/hashalgs", OREAD|OCEXEC);
+	j = open("/net/tls/hashalgs", OREAD|OCEXEC);
 	if(j < 0){
-		werrstr("can't open #a/tls/hashalgs: %r");
+		werrstr("can't open /net/tls/hashalgs: %r");
 		goto out;
 	}
 	n = read(j, s, MaxAlgF-1);
 	close(j);
 	if(n <= 0){
-		werrstr("nothing in #a/tls/hashalgs: %r");
+		werrstr("nothing in /net/tls/hashalgs: %r");
 		goto out;
 	}
 	s[n] = 0;
@@ -2306,6 +2348,7 @@
 	for(i = 0; i < nelem(cipherAlgs); i++)
 		if(cipherAlgs[i].ok && isPSK(cipherAlgs[i].tlsid) == ispsk)
 			is->data[j++] = cipherAlgs[i].tlsid;
+	is->data[j++] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV;
 	is->len = j;
 	return is;
 }