Re: relayd: SNI

2019-05-13 Thread Reyk Floeter
On Thu, May 09, 2019 at 02:51:23PM +0200, Reyk Floeter wrote:
> Hi,
> 
> this diff adds SNI support to relayd.
> 

Below is the same diff again -current minus one debug line.

jsing@ has noted that calling tls_config_set_keypair_ocsp_mem() with
NULL ocsp options could be replaced with tls_config_set_keypair_mem(),
but I'd like to keep it for now because I have an OCSP diff on top of
it that I'll send once SNI is in.

OK?

Reyk

Index: usr.sbin/relayd/ca.c
===
RCS file: /cvs/src/usr.sbin/relayd/ca.c,v
retrieving revision 1.34
diff -u -p -u -p -r1.34 ca.c
--- usr.sbin/relayd/ca.c19 Sep 2018 11:28:02 -  1.34
+++ usr.sbin/relayd/ca.c13 May 2019 08:53:17 -
@@ -108,56 +108,60 @@ hash_x509(X509 *cert, char *hash, size_t
 void
 ca_launch(void)
 {
-   char hash[TLS_CERT_HASH_SIZE];
-   char*buf;
-   BIO *in = NULL;
-   EVP_PKEY*pkey = NULL;
-   struct relay*rlay;
-   X509*cert = NULL;
-   off_tlen;
+   char hash[TLS_CERT_HASH_SIZE];
+   char*buf;
+   BIO *in = NULL;
+   EVP_PKEY*pkey = NULL;
+   struct relay*rlay;
+   struct relay_cert   *cert;
+   X509*x509 = NULL;
+   off_tlen;
 
-   TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
-   if ((rlay->rl_conf.flags & (F_TLS|F_TLSCLIENT)) == 0)
+   TAILQ_FOREACH(cert, env->sc_certs, cert_entry) {
+   if (cert->cert_fd == -1 || cert->cert_key_fd == -1)
continue;
 
-   if (rlay->rl_tls_cert_fd != -1) {
-   if ((buf = relay_load_fd(rlay->rl_tls_cert_fd,
-   )) == NULL)
-   fatal("ca_launch: cert relay_load_fd");
+   if ((buf = relay_load_fd(cert->cert_fd, )) == NULL)
+   fatal("ca_launch: cert relay_load_fd");
 
-   if ((in = BIO_new_mem_buf(buf, len)) == NULL)
-   fatalx("ca_launch: cert BIO_new_mem_buf");
+   if ((in = BIO_new_mem_buf(buf, len)) == NULL)
+   fatalx("ca_launch: cert BIO_new_mem_buf");
 
-   if ((cert = PEM_read_bio_X509(in, NULL,
-   NULL, NULL)) == NULL)
-   fatalx("ca_launch: cert PEM_read_bio_X509");
+   if ((x509 = PEM_read_bio_X509(in, NULL,
+   NULL, NULL)) == NULL)
+   fatalx("ca_launch: cert PEM_read_bio_X509");
 
-   hash_x509(cert, hash, sizeof(hash));
+   hash_x509(x509, hash, sizeof(hash));
 
-   BIO_free(in);
-   X509_free(cert);
-   purge_key(, len);
-   }
-   if (rlay->rl_conf.tls_key_len) {
-   if ((in = BIO_new_mem_buf(rlay->rl_tls_key,
-   rlay->rl_conf.tls_key_len)) == NULL)
-   fatalx("%s: key", __func__);
-
-   if ((pkey = PEM_read_bio_PrivateKey(in,
-   NULL, NULL, NULL)) == NULL)
-   fatalx("%s: PEM", __func__);
-   BIO_free(in);
+   BIO_free(in);
+   X509_free(x509);
+   purge_key(, len);
 
-   rlay->rl_tls_pkey = pkey;
+   if ((buf = relay_load_fd(cert->cert_key_fd, )) == NULL)
+   fatal("ca_launch: key relay_load_fd");
 
-   if (pkey_add(env, pkey, hash) == NULL)
-   fatalx("tls pkey");
+   if ((in = BIO_new_mem_buf(buf, len)) == NULL)
+   fatalx("%s: key", __func__);
 
-   purge_key(>rl_tls_key,
-   rlay->rl_conf.tls_key_len);
-   }
+   if ((pkey = PEM_read_bio_PrivateKey(in,
+   NULL, NULL, NULL)) == NULL)
+   fatalx("%s: PEM", __func__);
 
-   if (rlay->rl_tls_cacert_fd != -1) {
+   cert->cert_pkey = pkey;
+
+   if (pkey_add(env, pkey, hash) == NULL)
+   fatalx("tls pkey");
+
+   BIO_free(in);
+   purge_key(, len);
+   }
+
+   TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
+   if ((rlay->rl_conf.flags & (F_TLS|F_TLSCLIENT)) == 0)
+   continue;
+
+   if (rlay->rl_tls_cacert_fd != -1 &&
+   rlay->rl_conf.tls_cakey_len) {
if ((buf = relay_load_fd(rlay->rl_tls_cacert_fd,
)) == NULL)
fatal("ca_launch: cacert relay_load_fd");
@@ -165,17 +169,16 @@ 

relayd: SNI

2019-05-09 Thread Reyk Floeter
Hi,

this diff adds SNI support to relayd.

It is a bit big and I have to break it down, but I'm sending this
first version now to give people a chance to test.  The major
"infrastructure" change is that keypairs are not stored in relay
structs anymore but in a global list where each keypair ("cert") is
associated to a relay id.

relayd currently loads the keypair using the listen address as the
file name for the .key and .crt files.  I decided to keep this
behavior.  The new optional "tls keypair" argument allows to specify
one or more keypairs by name instead and they will be loaded as .key
and .crt files accordingly.

```relayd.conf
protocol foo {
tls keypair "localhost"
tls keypair "server"
# Or: tls { keypair "localhost", keypair "server" }
}

relay assl {
listen on 127.0.0.1 port 443 tls
protocol foo
forward to 199.233.217.205 port 80
}
```

Results in:
relay_load_certfiles: using certificate /etc/ssl/localhost.crt
relay_load_certfiles: using private key /etc/ssl/private/localhost.key
relay_load_certfiles: using certificate /etc/ssl/server.crt
relay_load_certfiles: using private key /etc/ssl/private/server.key

Connecting to relayd now gives you certificates based on the server
name, using the first one as the default.

Comments?

Reyk

Index: usr.sbin/relayd/ca.c
===
RCS file: /cvs/src/usr.sbin/relayd/ca.c,v
retrieving revision 1.34
diff -u -p -u -p -r1.34 ca.c
--- usr.sbin/relayd/ca.c19 Sep 2018 11:28:02 -  1.34
+++ usr.sbin/relayd/ca.c9 May 2019 12:35:40 -
@@ -108,56 +108,60 @@ hash_x509(X509 *cert, char *hash, size_t
 void
 ca_launch(void)
 {
-   char hash[TLS_CERT_HASH_SIZE];
-   char*buf;
-   BIO *in = NULL;
-   EVP_PKEY*pkey = NULL;
-   struct relay*rlay;
-   X509*cert = NULL;
-   off_tlen;
+   char hash[TLS_CERT_HASH_SIZE];
+   char*buf;
+   BIO *in = NULL;
+   EVP_PKEY*pkey = NULL;
+   struct relay*rlay;
+   struct relay_cert   *cert;
+   X509*x509 = NULL;
+   off_tlen;
 
-   TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
-   if ((rlay->rl_conf.flags & (F_TLS|F_TLSCLIENT)) == 0)
+   TAILQ_FOREACH(cert, env->sc_certs, cert_entry) {
+   if (cert->cert_fd == -1 || cert->cert_key_fd == -1)
continue;
 
-   if (rlay->rl_tls_cert_fd != -1) {
-   if ((buf = relay_load_fd(rlay->rl_tls_cert_fd,
-   )) == NULL)
-   fatal("ca_launch: cert relay_load_fd");
+   if ((buf = relay_load_fd(cert->cert_fd, )) == NULL)
+   fatal("ca_launch: cert relay_load_fd");
 
-   if ((in = BIO_new_mem_buf(buf, len)) == NULL)
-   fatalx("ca_launch: cert BIO_new_mem_buf");
+   if ((in = BIO_new_mem_buf(buf, len)) == NULL)
+   fatalx("ca_launch: cert BIO_new_mem_buf");
 
-   if ((cert = PEM_read_bio_X509(in, NULL,
-   NULL, NULL)) == NULL)
-   fatalx("ca_launch: cert PEM_read_bio_X509");
+   if ((x509 = PEM_read_bio_X509(in, NULL,
+   NULL, NULL)) == NULL)
+   fatalx("ca_launch: cert PEM_read_bio_X509");
 
-   hash_x509(cert, hash, sizeof(hash));
+   hash_x509(x509, hash, sizeof(hash));
 
-   BIO_free(in);
-   X509_free(cert);
-   purge_key(, len);
-   }
-   if (rlay->rl_conf.tls_key_len) {
-   if ((in = BIO_new_mem_buf(rlay->rl_tls_key,
-   rlay->rl_conf.tls_key_len)) == NULL)
-   fatalx("%s: key", __func__);
-
-   if ((pkey = PEM_read_bio_PrivateKey(in,
-   NULL, NULL, NULL)) == NULL)
-   fatalx("%s: PEM", __func__);
-   BIO_free(in);
+   BIO_free(in);
+   X509_free(x509);
+   purge_key(, len);
 
-   rlay->rl_tls_pkey = pkey;
+   if ((buf = relay_load_fd(cert->cert_key_fd, )) == NULL)
+   fatal("ca_launch: key relay_load_fd");
 
-   if (pkey_add(env, pkey, hash) == NULL)
-   fatalx("tls pkey");
+   if ((in = BIO_new_mem_buf(buf, len)) == NULL)
+   fatalx("%s: key", __func__);
 
-   purge_key(>rl_tls_key,
-   rlay->rl_conf.tls_key_len);
-   }
+   if ((pkey