shithub: tlssrv.sni

ref: fe1ec8fd63507f3972c7d89ceba694477d570be4
dir: /README/

View raw version
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);
}