maybe session cache disable should disable tickets too.

some little things below, otherwise ok

Claudio Jeker([email protected]) on 2016.07.19 15:32:13 +0200:
> At the moment relayd's TLS session caching is a bit busted because
> the multiple relay processes do not share state.
> The following diff adds SSL session caching and sharing of the TLS ticket
> secrets. Which this openssl s_client -connect W.X.Y.Z:443 -reconnect
> reuses the connection after the first one.
> This should help TLS preformance since no exchange with the ca process is
> needed if there is a cache hit.
> 
> The shared SSL session cache is in a new process (tlsc) but we still use
> the internal cache as well (which is populated on cache miss).
> 
> The TLS token secret are generated on startup and a key rollover happens
> every 4h with a rekey window of 10min. I see no need to add tunables for
> this and also the shared SSL cache will just use the tls session cache
> settings (because OpenSSL will do the garbage collection of the external
> cache via the internal one).
> 
> This is the first version which seems to work for me when hammering relayd
> with openssl s_client.
> -- 
> :wq Claudio
> 
> 
> Index: Makefile
> ===================================================================
> RCS file: /cvs/src/usr.sbin/relayd/Makefile,v
> retrieving revision 1.29
> diff -u -p -r1.29 Makefile
> --- Makefile  21 Nov 2015 12:37:42 -0000      1.29
> +++ Makefile  19 Jul 2016 08:33:26 -0000
> @@ -6,7 +6,7 @@ SRCS+=                agentx.c ca.c carp.c check_icmp.
>               check_tcp.c config.c control.c hce.c log.c name2id.c \
>               pfe.c pfe_filter.c pfe_route.c proc.c \
>               relay.c relay_http.c relay_udp.c relayd.c \
> -             shuffle.c snmp.c ssl.c util.c
> +             shuffle.c snmp.c ssl.c tlsc.c util.c
>  MAN=         relayd.8 relayd.conf.5
>  
>  LDADD=               -levent -lssl -lcrypto -lutil
> Index: ca.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/relayd/ca.c,v
> retrieving revision 1.16
> diff -u -p -r1.16 ca.c
> --- ca.c      5 Dec 2015 13:13:11 -0000       1.16
> +++ ca.c      19 Jul 2016 13:18:33 -0000
> @@ -23,6 +23,7 @@
>  #include <unistd.h>
>  #include <string.h>
>  #include <stdlib.h>
> +#include <poll.h>
>  #include <imsg.h>
>  
>  #include <openssl/bio.h>
> @@ -256,6 +257,7 @@ static int
>  rsae_send_imsg(int flen, const u_char *from, u_char *to, RSA *rsa,
>      int padding, u_int cmd)
>  {
> +     struct pollfd    pfd[1];
>       struct ctl_keyop cko;
>       int              ret = 0;
>       objid_t         *id;
> @@ -292,9 +294,21 @@ rsae_send_imsg(int flen, const u_char *f
>        * operation in OpenSSL's engine layer.
>        */
>       imsg_composev(ibuf, cmd, 0, 0, -1, iov, cnt);
> -     imsg_flush(ibuf);
> +     if (imsg_flush(ibuf) == -1)
> +             log_warn("rsae_send_imsg: imsg_flush");
>  
> +     pfd[0].fd = ibuf->fd;
> +     pfd[0].events = POLLIN;
>       while (!done) {
> +             switch (poll(pfd, 1, 5 * 1000)) {
> +             case -1:
> +                     fatal("rsae_send_imsg: poll");
> +             case 0:
> +                     log_warnx("rsae_send_imsg: poll timeout");
> +                     break;
> +             default:
> +                     break;
> +             }
>               if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
>                       fatalx("imsg_read");
>               if (n == 0)
> Index: config.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/relayd/config.c,v
> retrieving revision 1.27
> diff -u -p -r1.27 config.c
> --- config.c  7 Dec 2015 04:03:27 -0000       1.27
> +++ config.c  18 Jul 2016 13:01:35 -0000
> @@ -51,6 +51,7 @@ config_init(struct relayd *env)
>               ps->ps_what[PROC_CA] = CONFIG_RELAYS;
>               ps->ps_what[PROC_RELAY] = CONFIG_RELAYS|
>                   CONFIG_TABLES|CONFIG_PROTOS|CONFIG_CA_ENGINE;
> +             ps->ps_what[PROC_TLSC] = 0;
>       }
>  
>       /* Other configuration */
> Index: relay.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/relayd/relay.c,v
> retrieving revision 1.206
> diff -u -p -r1.206 relay.c
> --- relay.c   30 Dec 2015 16:00:57 -0000      1.206
> +++ relay.c   19 Jul 2016 13:17:57 -0000
> @@ -28,6 +28,7 @@
>  #include <arpa/inet.h>
>  
>  #include <limits.h>
> +#include <poll.h>
>  #include <stdio.h>
>  #include <stdlib.h>
>  #include <errno.h>
> @@ -54,6 +55,8 @@ int          relay_dispatch_ca(int, struct priv
>                   struct imsg *);
>  int           relay_dispatch_hce(int, struct privsep_proc *,
>                   struct imsg *);
> +int           relay_dispatch_tlsc(int, struct privsep_proc *,
> +                 struct imsg *);
>  void          relay_shutdown(void);
>  
>  void          relay_protodebug(struct relay *);
> @@ -84,6 +87,13 @@ void                relay_tls_connect(int, short, voi
>  void          relay_tls_connected(struct ctl_relay_event *);
>  void          relay_tls_readcb(int, short, void *);
>  void          relay_tls_writecb(int, short, void *);
> +int           relay_tls_new_session(SSL *, SSL_SESSION *);
> +SSL_SESSION  *relay_tls_get_session(SSL *, unsigned char *, int, int *);
> +void          relay_tls_del_session(SSL_CTX *, SSL_SESSION *);
> +
> +struct tls_ticket_ctx        *relay_get_ticket_key(unsigned char [16]);
> +int                   relay_tls_session_ticket(SSL *, unsigned char [16],
> +                         unsigned char *, EVP_CIPHER_CTX *, HMAC_CTX *, int);
>  
>  char         *relay_load_file(const char *, off_t *);
>  extern void   bufferevent_read_pressure_cb(struct evbuffer *, size_t,
> @@ -92,6 +102,8 @@ extern void         bufferevent_read_pressure_c
>  volatile int relay_sessions;
>  volatile int relay_inflight = 0;
>  objid_t relay_conid;
> +static u_int8_t                       sid[SSL_MAX_SID_CTX_LENGTH];
> +static struct tls_ticket_ctx  tls_ticket, tls_ticket_bak;
>  
>  static struct relayd         *env = NULL;
>  int                           proc_id;
> @@ -101,12 +113,18 @@ static struct privsep_proc procs[] = {
>       { "pfe",        PROC_PFE,       relay_dispatch_pfe },
>       { "ca",         PROC_CA,        relay_dispatch_ca },
>       { "hce",        PROC_HCE,       relay_dispatch_hce },
> +     { "tlsc",       PROC_TLSC,      relay_dispatch_tlsc },
>  };
>  
>  pid_t
>  relay(struct privsep *ps, struct privsep_proc *p)
>  {
>       pid_t    pid;
> +
> +     /* initialize the session id to a random key for all relay procs */
> +     arc4random_buf(sid, sizeof(sid));
> +     tlsc_create_ticket(&tls_ticket);
> +
>       env = ps->ps_env;
>       pid = proc_run(ps, p, procs, nitems(procs), relay_init, NULL);
>       relay_http(env);
> @@ -1931,6 +1949,23 @@ relay_dispatch_parent(int fd, struct pri
>       return (0);
>  }
>  
> +int
> +relay_dispatch_tlsc(int fd, struct privsep_proc *p, struct imsg *imsg)
> +{
> +     switch (imsg->hdr.type) {
> +     case IMSG_TLSC_REKEY:
> +             IMSG_SIZE_CHECK(imsg, (&tls_ticket));
> +             /* rotate keys */
> +             memcpy(&tls_ticket_bak, &tls_ticket, sizeof(tls_ticket));
> +             memcpy(&tls_ticket, imsg->data, sizeof(tls_ticket));
> +             break;
> +     default:
> +             return (-1);
> +     }
> +
> +     return (0);
> +}
> +
>  void
>  relay_tls_callback_info(const SSL *ssl, int where, int rc)
>  {
> @@ -2045,7 +2080,6 @@ relay_tls_ctx_create(struct relay *rlay)
>       struct protocol *proto = rlay->rl_proto;
>       SSL_CTX         *ctx;
>       EC_KEY          *ecdhkey;
> -     u_int8_t         sid[SSL_MAX_SID_CTX_LENGTH];
>  
>       ctx = SSL_CTX_new(SSLv23_method());
>       if (ctx == NULL)
> @@ -2058,10 +2092,18 @@ relay_tls_ctx_create(struct relay *rlay)
>               SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
>       } else if (proto->cache >= -1) {
>               SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
> -             if (proto->cache >= 0)
> +             if (proto->cache >= 0) {
>                       SSL_CTX_sess_set_cache_size(ctx, proto->cache);
> +             }
> +             SSL_CTX_sess_set_new_cb(ctx, relay_tls_new_session);
> +             SSL_CTX_sess_set_get_cb(ctx, relay_tls_get_session);
> +             SSL_CTX_sess_set_remove_cb(ctx, relay_tls_del_session);
>       }
>  
> +     /* Callback for TLS session tickets */
> +     if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, relay_tls_session_ticket))
> +             log_warnx("could not set the TLS ticket callback");
> +
>       /* Enable all workarounds and set SSL options */
>       SSL_CTX_set_options(ctx, SSL_OP_ALL);
>       SSL_CTX_set_options(ctx,
> @@ -2142,11 +2184,9 @@ relay_tls_ctx_create(struct relay *rlay)
>       }
>  
>       /*
> -      * Set session ID context to a random value.  We don't support
> -      * persistent caching of sessions so it is OK to set a temporary
> -      * session ID context that is valid during run time.
> +      * Set session ID context to a random value. It needs to be the
> +      * same accross all relay processes or session caching will fail.
>        */
> -     arc4random_buf(sid, sizeof(sid));
>       if (!SSL_CTX_set_session_id_context(ctx, sid, sizeof(sid)))
>               goto err;
>  
> @@ -2534,6 +2574,156 @@ relay_tls_writecb(int fd, short event, v
>               cre->buflen = 0;
>       }
>       (*bufev->errorcb)(bufev, what, bufev->cbarg);
> +}
> +
> +int
> +relay_tls_new_session(SSL *ssl, SSL_SESSION *session)
> +{
> +     const unsigned char *id;
> +     unsigned char *buf, *s;
> +     unsigned int idlen;
> +     long timeout;
> +     int slen;
> +
> +     timeout = SSL_SESSION_get_timeout(session);
> +
> +     id = SSL_SESSION_get_id(session, &idlen);
> +
> +     /* Serialise the session. */
> +     slen = i2d_SSL_SESSION(session, NULL);
> +     if ((buf = s = malloc(slen)) == NULL)
> +             fatal("relay_tls_new_session");
> +     if (slen != i2d_SSL_SESSION(session, &buf))
> +             fatalx("SSL SESSION unexpectly grew beyond buffer");
> +
> +     tlsc_modify(env, IMSG_TLSC_ADD, id, idlen, s, slen, timeout);
> +
> +     free(s);
> +     return 0;       /* tell SSL to remove the reference on the session */
> +}
> +
> +SSL_SESSION *
> +relay_tls_get_session(SSL *ssl, unsigned char *id, int idlen, int *do_copy)
> +{
> +     struct pollfd            pfd[1];
> +     struct iovec             iov[3];
> +     SSL_SESSION             *session = NULL;
> +     struct imsgbuf          *ibuf;
> +     const unsigned char     *data;
> +     struct imsg              imsg;
> +     int                      proc;
> +     int                      n, done = 0, cnt = 0;
> +
> +     ibuf = proc_ibuf(env->sc_ps, PROC_TLSC, -1);
> +     proc = proc_id;
> +
> +     iov[cnt].iov_base = &proc;
> +     iov[cnt++].iov_len = sizeof(proc);
> +     iov[cnt].iov_base = (void *)id;
> +     iov[cnt++].iov_len = idlen;
> +
> +     imsg_composev(ibuf, IMSG_TLSC_GET, 0, 0, -1, iov, cnt);
> +     if (imsg_flush(ibuf) == -1)
> +             log_warn("tlsc_lookup: imsg_flush");
> +
> +     pfd[0].fd = ibuf->fd;
> +     pfd[0].events = POLLIN;
> +     while (!done) {
> +             switch (poll(pfd, 1, 5 * 1000)) {
> +             case -1:
> +                     fatal("rsae_send_imsg: poll");
> +             case 0:
> +                     log_warnx("tlsc_lookup: poll timeout");
> +                     break;
> +             default:
> +                     break;
> +             }
> +             if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
> +                     fatalx("imsg_read");
> +             if (n == 0)
> +                     fatalx("pipe closed");
> +
> +             while (!done) {
> +                     if ((n = imsg_get(ibuf, &imsg)) == -1)
> +                             fatalx("imsg_get error");
> +                     if (n == 0)
> +                             break;
> +                     if (imsg.hdr.type != IMSG_TLSC_GET)
> +                             fatalx("invalid response");
> +
> +                     if (IMSG_DATA_SIZE(&imsg) != 0) {
> +                             data = imsg.data;
> +                             session = d2i_SSL_SESSION(NULL, &data,
> +                                 IMSG_DATA_SIZE(&imsg));
> +                     }
> +                     done = 1;
> +                     imsg_free(&imsg);
> +             }
> +     }
> +
> +     *do_copy = 0;
> +     return (session);
> +}
> +
> +void
> +relay_tls_del_session(SSL_CTX *ssl, SSL_SESSION *session)
> +{
> +     unsigned char *id;
> +     unsigned int idlen;
> +
> +     id = (unsigned char *)SSL_SESSION_get_id(session, &idlen);
> +     tlsc_modify(env, IMSG_TLSC_DEL, id, idlen, NULL, 0, 0);
> +}
> +
> +struct tls_ticket_ctx *
> +relay_get_ticket_key(unsigned char keyname[16])
> +{
> +     if (keyname) {
> +             if (timingsafe_memcmp(keyname,
> +                 tls_ticket_bak.key_name, sizeof(keyname)) == 0)
> +                     return &tls_ticket_bak;
> +             if (timingsafe_memcmp(keyname,
> +                 tls_ticket.key_name, sizeof(keyname)) == 0)
> +                     return &tls_ticket;
> +             return NULL;
> +     }
> +     return &tls_ticket;
> +}
> +
> +int
> +relay_tls_session_ticket(SSL *ssl, unsigned char keyname[16], unsigned char 
> *iv,
> +    EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int mode)
> +{
> +     struct tls_ticket_ctx   *key;
> +     struct timespec          ts;
> +
> +     if (mode == 1) {
> +             /* create new session */
> +             key = relay_get_ticket_key(NULL);
> +             memcpy(keyname, key->key_name, 16);
> +             arc4random_buf(iv, EVP_MAX_IV_LENGTH);
> +             EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL,
> +                 key->aes_key, iv);
> +             HMAC_Init_ex(hctx, key->hmac_key, 16, EVP_sha256(), NULL);
> +             return 0;
> +     } else {
> +             if (clock_gettime(CLOCK_MONOTONIC, &ts))
> +                     fatal("clock_gettime");
> +
> +             /* get key by name */
> +             key = relay_get_ticket_key(keyname);
> +             if  (!key || key->expire < ts.tv_sec)
> +                     return 0;
> +
> +             EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL,
> +                 key->aes_key, iv);
> +             HMAC_Init_ex(hctx, key->hmac_key, 16, EVP_sha256(), NULL);
> +
> +             /* time to renew the ticket? */
> +             if (key->expire - TLS_TICKET_RENEW_TIME < ts.tv_sec)
> +                     return 2;
> +             return 1;
> +     }
>  }
>  
>  int
> Index: relayd.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/relayd/relayd.c,v
> retrieving revision 1.153
> diff -u -p -r1.153 relayd.c
> --- relayd.c  2 Feb 2016 17:51:11 -0000       1.153
> +++ relayd.c  19 Jul 2016 10:00:03 -0000
> @@ -70,7 +70,8 @@ static struct privsep_proc procs[] = {
>       { "pfe",        PROC_PFE, parent_dispatch_pfe, pfe },
>       { "hce",        PROC_HCE, parent_dispatch_hce, hce },
>       { "relay",      PROC_RELAY, parent_dispatch_relay, relay },
> -     { "ca",         PROC_CA, parent_dispatch_ca, ca }
> +     { "ca",         PROC_CA, parent_dispatch_ca, ca },
> +     { "tlsc",       PROC_TLSC, NULL, tlsc }
>  };
>  
>  void
> @@ -635,6 +636,8 @@ purge_relay(struct relayd *env, struct r
>               rlay->rl_tls_capkey = NULL;
>       }
>  
> +     if (rlay->rl_ssl_ctx)
> +             SSL_CTX_sess_set_remove_cb(rlay->rl_ssl_ctx, NULL);
>       SSL_CTX_free(rlay->rl_ssl_ctx);
>  
>       while ((rlt = TAILQ_FIRST(&rlay->rl_tables))) {
> Index: relayd.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/relayd/relayd.h,v
> retrieving revision 1.222
> diff -u -p -r1.222 relayd.h
> --- relayd.h  11 Jan 2016 21:31:42 -0000      1.222
> +++ relayd.h  19 Jul 2016 13:07:36 -0000
> @@ -961,7 +961,11 @@ enum imsg_type {
>       IMSG_CA_PRIVENC,
>       IMSG_CA_PRIVDEC,
>       IMSG_SESS_PUBLISH,      /* from relay to hce */
> -     IMSG_SESS_UNPUBLISH
> +     IMSG_SESS_UNPUBLISH,
> +     IMSG_TLSC_ADD,
> +     IMSG_TLSC_GET,
> +     IMSG_TLSC_DEL,
> +     IMSG_TLSC_REKEY
>  };
>  
>  enum privsep_procid {
> @@ -971,6 +975,7 @@ enum privsep_procid {
>       PROC_RELAY,
>       PROC_PFE,
>       PROC_CA,
> +     PROC_TLSC,
>       PROC_MAX
>  } privsep_process;
>  
> @@ -1076,6 +1081,15 @@ struct relayd {
>       int                      sc_reload;
>  };
>  
> +struct tls_ticket_ctx {
> +     time_t          expire;
> +     unsigned char   key_name[16];
> +     unsigned char   aes_key[16];
> +     unsigned char   hmac_key[16];
> +};
> +#define      TLS_TICKET_LIFE_TIME    (4 * 3600)
> +#define      TLS_TICKET_RENEW_TIME   600
> +
>  #define      FSNMP_TRAPONLY                  0x01
>  
>  #define RELAYD_OPT_VERBOSE           0x01
> @@ -1237,6 +1251,13 @@ int     ssl_ctx_fake_private_key(SSL_CTX *,
>  /* ca.c */
>  pid_t         ca(struct privsep *, struct privsep_proc *);
>  void  ca_engine_init(struct relayd *);
> +
> +/* tlsc.c */
> +pid_t         tlsc(struct privsep *, struct privsep_proc *);
> +void  tlsc_engine_init(struct relayd *);
> +void  tlsc_modify(struct relayd *, u_int, const void *, size_t,
> +         void *, size_t, long);
> +void  tlsc_create_ticket(struct tls_ticket_ctx *);
>  
>  /* relayd.c */
>  struct host  *host_find(struct relayd *, objid_t);
> Index: tlsc.c
> ===================================================================
> RCS file: tlsc.c
> diff -N tlsc.c
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ tlsc.c    19 Jul 2016 13:30:01 -0000
> @@ -0,0 +1,336 @@
> +/*   $OpenBSD$       */
> +
> +/*
> + * Copyright (c) 2016 Claudio Jeker <[email protected]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/queue.h>
> +#include <sys/tree.h>
> +#include <sys/uio.h>
> +
> +#include <unistd.h>
> +#include <string.h>
> +#include <stdlib.h>
> +#include <poll.h>
> +#include <imsg.h>
> +
> +#include "relayd.h"
> +
> +struct tlsc_hdr {
> +     size_t idlen;
> +     size_t slen;
> +     long   timeout;
> +};
> +
> +struct tlsc_get {
> +     size_t  idlen;
> +     int     proc;
> +};
> +
> +struct tlsc {
> +     RB_ENTRY(tlsc)          entry;
> +     size_t                  idlen;
> +     size_t                  slen;
> +     time_t                  expire;
> +     const unsigned char     *id;
> +     const unsigned char     *session;
> +};
> +
> +void tlsc_init(struct privsep *, struct privsep_proc *p, void *);
> +void tlsc_launch(void);
> +void tlsc_rekey(int, short, void *);
> +int  tlsc_dispatch_parent(int, struct privsep_proc *, struct imsg *);
> +int  tlsc_dispatch_relay(int, struct privsep_proc *, struct imsg *);
> +
> +int           tlsc_compare(struct tlsc *, struct tlsc *);
> +struct tlsc  *tlsc_get(const void *, size_t);
> +void          tlsc_add(const void *, size_t, const void *, size_t, long);
> +void          tlsc_del(const void *, size_t);
> +void          tlsc_flush(void);
> +
> +void tlsc_dump(const char *pre, const void *id, size_t idlen);
> +
> +RB_HEAD(tlsc_tree, tlsc) tls_cache = RB_INITIALIZER(&tls_cache);
> +RB_PROTOTYPE(tlsc_tree, tlsc, entry, tlsc_compare)
> +RB_GENERATE(tlsc_tree, tlsc, entry, tlsc_compare)
> +
> +static struct relayd *env = NULL;
> +extern int            proc_id;
> +
> +static struct event  rekeyev;
> +
> +static struct privsep_proc procs[] = {
> +     { "parent",     PROC_PARENT,    tlsc_dispatch_parent },
> +     { "relay",      PROC_RELAY,     tlsc_dispatch_relay },
> +};
> +
> +pid_t
> +tlsc(struct privsep *ps, struct privsep_proc *p)
> +{
> +     env = ps->ps_env;
> +
> +     return (proc_run(ps, p, procs, nitems(procs), tlsc_init, NULL));
> +}
> +
> +void
> +tlsc_init(struct privsep *ps, struct privsep_proc *p, void *arg)
> +{
> +     if (pledge("stdio", NULL) == -1)
> +             fatal("pledge");
> +
> +     if (config_init(ps->ps_env) == -1)
> +             fatal("failed to initialize configuration");
> +}
> +
> +void
> +tlsc_launch(void)
> +{
> +     struct timeval   tv;
> +
> +     /* flush the cache after reconfigure, the same happens in the relays */
> +     tlsc_flush();
> +
> +        /* Schedule statistics timer */

indent?

> +     evtimer_set(&rekeyev, tlsc_rekey, NULL);
> +     bzero(&tv, sizeof(tv));
> +     tv.tv_sec = TLS_TICKET_LIFE_TIME;
> +     evtimer_add(&rekeyev, &tv);
> +}
> +
> +void
> +tlsc_rekey(int fd, short events, void *arg)
> +{
> +     struct timeval          tv;

whitespace

> +     struct tls_ticket_ctx   ticket;
> +     
> +     log_debug("tlsc_rekey: rekeying tickets");
> +
> +     tlsc_create_ticket(&ticket);
> +     proc_compose_imsg(env->sc_ps, PROC_RELAY, -1, IMSG_TLSC_REKEY, -1, -1,
> +         &ticket, sizeof(ticket));
> +
> +     evtimer_set(&rekeyev, tlsc_rekey, NULL);
> +     bzero(&tv, sizeof(tv));
> +     tv.tv_sec = TLS_TICKET_LIFE_TIME;
> +     evtimer_add(&rekeyev, &tv);
> +}
> +
> +int
> +tlsc_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
> +{
> +     switch (imsg->hdr.type) {
> +     case IMSG_CTL_START:
> +             tlsc_launch();
> +             break;
> +     case IMSG_CFG_DONE:
> +             /* nothing to do here */
> +             break;
> +     default:
> +             return -1;
> +     }
> +     return 0;
> +}
> +
> +int
> +tlsc_dispatch_relay(int fd, struct privsep_proc *p, struct imsg *imsg)
> +{
> +     struct tlsc_hdr  th;
> +     int              proc;
> +     unsigned char   *id, *s;
> +     struct tlsc     *t;
> +
> +     switch (imsg->hdr.type) {
> +     case IMSG_TLSC_ADD:
> +     case IMSG_TLSC_DEL:
> +             IMSG_SIZE_CHECK(imsg, (&th));
> +             memcpy(&th, imsg->data, sizeof(th));
> +             if (IMSG_DATA_SIZE(imsg) != (sizeof(th) + th.idlen + th.slen))
> +                     fatalx("tlsc_dispatch_relay: bad TLS cache imsg");
> +             id = (unsigned char *)imsg->data + sizeof(th);
> +             s = id + th.idlen;
> +
> +             switch (imsg->hdr.type) {
> +             case IMSG_TLSC_ADD:
> +                     tlsc_add(id, th.idlen, s, th.slen, th.timeout);
> +                     break;
> +             case IMSG_TLSC_DEL:
> +                     tlsc_del(id, th.idlen);
> +                     break;
> +             }
> +             break;
> +     case IMSG_TLSC_GET:
> +             IMSG_SIZE_CHECK(imsg, (&proc));
> +             memcpy(&proc, imsg->data, sizeof(proc));
> +
> +             t = tlsc_get((unsigned char *)imsg->data + sizeof(proc),
> +                 IMSG_DATA_SIZE(imsg) - sizeof(proc));
> +             if (t == NULL)
> +                     proc_compose_imsg(env->sc_ps, PROC_RELAY, proc,
> +                         imsg->hdr.type, -1, -1, NULL, 0);
> +             else
> +                     proc_compose_imsg(env->sc_ps, PROC_RELAY, proc,
> +                         imsg->hdr.type, -1, -1,
> +                         (void *)t->session, t->slen);
> +             break;
> +     default:
> +             return (-1);
> +     }
> +
> +     return (0);
> +}
> +
> +void
> +tlsc_modify(struct relayd *e, u_int cmd, const void *id, size_t idlen,
> +    void *s, size_t slen, long timeout)
> +{
> +     struct iovec     iov[3];
> +     struct imsgbuf  *ibuf;
> +     struct tlsc_hdr  th;
> +     int              cnt = 0;
> +
> +
> +     ibuf = proc_ibuf(e->sc_ps, PROC_TLSC, -1);
> +
> +     /* build up imsg */
> +     th.timeout = timeout;
> +     th.idlen = idlen;
> +     if (s)
> +             th.slen = slen;
> +     else
> +             th.slen = 0;
> +
> +     iov[cnt].iov_base = &th;
> +     iov[cnt++].iov_len = sizeof(th);
> +     iov[cnt].iov_base = (void *)id;
> +     iov[cnt++].iov_len = idlen;
> +     if (s) {
> +             iov[cnt].iov_base = (void *)s;
> +             iov[cnt++].iov_len = slen;
> +     }
> +
> +     /* Fire and forget, imsg are reliable */

do we mention that fact elsewhere? ;)

> +     imsg_composev(ibuf, cmd, 0, 0, -1, iov, cnt);
> +     if (imsg_flush(ibuf) == -1)
> +             log_warn("tlsc_modify: imsg_flush");
> +}
> +
> +int
> +tlsc_compare(struct tlsc *a, struct tlsc *b)
> +{
> +     if (a->idlen < b->idlen)
> +             return -1;
> +     if (a->idlen > b->idlen)
> +             return 1;
> +     return memcmp(a->id, b->id, a->idlen);
> +}
> +
> +struct tlsc *
> +tlsc_get(const void *id, size_t idlen)
> +{ 
> +     struct tlsc     tt;
> +
> +     tlsc_dump("tlsc_get", id, idlen);
> +     memset(&tt, 0, sizeof(tt));
> +     tt.id = id;
> +     tt.idlen = idlen;
> +
> +     return RB_FIND(tlsc_tree, &tls_cache, &tt);
> +}
> +
> +void
> +tlsc_add(const void *id, size_t idlen, const void *s, size_t slen, long 
> timeout)
> +{
> +     struct timespec  ts;
> +     struct tlsc     *t;
> +     unsigned char   *b;
> +     size_t           l;
> +
> +     tlsc_dump("tlsc_add", id, idlen);
> +     l = sizeof(*t) + idlen + slen;
> +     if ((t = malloc(l)) == NULL)
> +             fatal("tlsc_add");
> +     memset(t, 0, sizeof(*t));
> +     b = (unsigned char *)(t + 1);
> +     memcpy(b, id, idlen);
> +     t->id = b;
> +     t->idlen = idlen;
> +     b += idlen;
> +     memcpy(b, s, slen);
> +     t->session = b;
> +     t->slen = slen;
> +
> +     if (clock_gettime(CLOCK_MONOTONIC, &ts))
> +             fatal("clock_gettime");
> +     t->expire = ts.tv_sec + timeout;
> +
> +     if (RB_INSERT(tlsc_tree, &tls_cache, t)) {
> +             log_warnx("tlsc_add: session already in cache");
> +             free(t);
> +     }
> +}
> +
> +void
> +tlsc_del(const void *id, size_t idlen)
> +{ 
> +     struct tlsc     *t;
> +
> +     tlsc_dump("tlsc_del", id, idlen);
> +     if ((t = tlsc_get(id, idlen)) == NULL) {
> +             log_warnx("tlsc_del: session not in cache");
> +             return;
> +     }
> +
> +     RB_REMOVE(tlsc_tree, &tls_cache, t);
> +     free(t);
> +}
> +
> +void
> +tlsc_flush(void)
> +{
> +     struct tlsc     *t;
> +
> +     while ((t = RB_MIN(tlsc_tree, &tls_cache)) != NULL) {
> +             RB_REMOVE(tlsc_tree, &tls_cache, t);
> +             free(t);
> +     }
> +}
> +
> +void
> +tlsc_dump(const char *pre, const void *id, size_t idlen)
> +{
> +     char buf[80];
> +     const unsigned char *s = id;
> +     size_t i;
> +
> +     for (i = 0; i < idlen; i++) {
> +             snprintf(buf + 2 * i, sizeof(buf) - 2 * i, "%02x", s[i]); 

space at the end

> +     }
> +     log_debug("%s id: %s", pre, buf);
> +}
> +
> +void
> +tlsc_create_ticket(struct tls_ticket_ctx *key)
> +{
> +     struct timespec ts;
> +
> +     if (clock_gettime(CLOCK_MONOTONIC, &ts))
> +             fatal("clock_gettime");
> +     key->expire = ts.tv_sec + TLS_TICKET_LIFE_TIME;
> +
> +     arc4random_buf(key->key_name, sizeof(key->key_name));
> +     arc4random_buf(key->hmac_key, sizeof(key->hmac_key));
> +     arc4random_buf(key->aes_key, sizeof(key->aes_key));
> +}
> 

-- 

Reply via email to