shithub: tlssrv.sni

Clone

clone: git://shithub.us/igor/tlssrv.sni gits://shithub.us/igor/tlssrv.sni
push: hjgit://shithub.us/igor/tlssrv.sni
patches to: igor@9lab.org

Last commit

fe1ec8fd – igor <igor@mux> authored on 2023/01/28 19:25
Describe the top level goal...

About

This is WIP attempting to extend tlssrv to support the Server Name
Identifier (SNI) extension.  With this extension it is possible to use
multiple SSL certificates with a single IP address.

# Key Functions

tlshand.c:/^tlsClientExtensions
tlshand.c:/^checkClientExtensions
tlshand.c:/^tlsConnectionFree

# Data Types

tlshand.c:/^typedef struct TlsConnection
/sys/include/libsec.h:/^typedef struct TLSconn

# Approach

The function tlshand.c:/^checkClientExtensions must
be extended to decode the server name indication. For this
the 'tlshand.c:/^typedef struct TlsConnection' needs to
be extended to hold the server name.

tlshand.c:/^tlsConnectionFree needs to free any potential
`TlsConnection.serverName`.

We are going to allow multiple certificates to be specified
to tlssrv. A certificate encodes its domain in its subject:

 % auth/pemdecode 'CERTIFICATE' /sys/lib/tls/acmed/mux.9lab.org.crt | auth/x5092pub
key proto=rsa size=2048 ek=10001 n=BEF7549C333817BBE366CD58B2A60D3D2E3C1924ADF9E9B6BDB7FB74B5FF0CF1FF5A4D7A6F7202B7155D854396E925ADEAAF27AF8A118E0360470D6FD01BBF710051B02A53ECBFA8A8BB0FADCD4C7E320296CC6E82DE71B3B9D0378B982DB0359E4C8FD2AF9CB9BC3B6CBC0931E6638F74E716AA7B7AAF9E0873DDA676073B9C4F499EE57D96BAD2C2FB156CC25C289EAAC962CE785C82D2CFD78CC2A493B0965224EAFE94AB0A14441EF0CE4BBC0BF1E4034CAD051131A08120221F56E7000CAAF2244D5B111F7764CF04BE1A4BC866721FC4F8C9BD35F4EB71BFF33982F7BEAB3246794610666896C01D572D674E9A27B2CBD2D2D9311DAD675BAF230B82BF subject=mux.9lab.org

Sample code that shows how to extract the domain from the
subject can be found in /sys/src/cmd/auth/acmed.c:/^getcert

static void
getcert(char *csrpath)
{
	char *csr, *dom[64], subj[2048];
	uchar *der;
	int nder, ndom, fd;
	RSApub *rsa;
	Hdr loc = { "location" };
	JSON *o;

	if((fd = open(csrpath, OREAD|OCEXEC)) == -1)
		sysfatal("open %s: %r", csrpath);
	if((der = slurp(fd, &nder)) == nil)
		sysfatal("read %s: %r", csrpath);
	close(fd);

	if((rsa = X509reqtoRSApub(der, nder, subj, sizeof(subj))) == nil)
		sysfatal("decode csr: %r");
	rsapubfree(rsa);
	if((csr = encurl64(der, nder)) == nil)
		sysfatal("encode %s: %r", csrpath);
	free(der);

	dprint("subject: %s\n", subj);
	if((ndom = getfields(subj, dom, nelem(dom), 1, ", ")) == nelem(dom))
		sysfatal("too man domains");

	if((o = submitorder(dom, ndom, &loc)) == nil)
		sysfatal("order: %r");
	if(dochallenges(dom, ndom, o) == -1)
		sysfatal("challenge: %r");

	if(submitcsr(o, csr) == -1)
		sysfatal("signing cert: %r");
	if(fetchcert(loc.val) == -1)
		sysfatal("saving cert: %r");

	free(csr);
}