On Sat, Mar 25, 2017 at 06:06:48PM +0100, Claudio Jeker wrote:
> I realized I never commited the ticket support in httpd that I added in
> Brisbane. Anyone want to give me an OK on it?
> 

diff reads fine OK reyk@

> Cheers
> -- 
> :wq Claudio
> 
> Index: config.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/httpd/config.c,v
> retrieving revision 1.50
> diff -u -p -r1.50 config.c
> --- config.c  6 Nov 2016 10:49:38 -0000       1.50
> +++ config.c  24 Jan 2017 11:21:35 -0000
> @@ -146,6 +146,7 @@ config_getcfg(struct httpd *env, struct 
>       memcpy(&cf, imsg->data, sizeof(cf));
>       env->sc_opts = cf.cf_opts;
>       env->sc_flags = cf.cf_flags;
> +     memcpy(env->sc_tls_sid, cf.cf_tls_sid, sizeof(env->sc_tls_sid));
>  
>       what = ps->ps_what[privsep_process];
>  
> @@ -238,6 +239,9 @@ config_setserver(struct httpd *env, stru
>               close(srv->srv_s);
>               srv->srv_s = -1;
>       }
> +
> +     explicit_bzero(&srv->srv_conf.tls_ticket_key,
> +         sizeof(srv->srv_conf.tls_ticket_key));
>  
>       return (0);
>  }
> Index: httpd.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/httpd/httpd.c,v
> retrieving revision 1.64
> diff -u -p -r1.64 httpd.c
> --- httpd.c   23 Jan 2017 04:25:05 -0000      1.64
> +++ httpd.c   25 Jan 2017 04:22:34 -0000
> @@ -57,6 +57,8 @@ int          parent_dispatch_server(int, struct
>                   struct imsg *);
>  int           parent_dispatch_logger(int, struct privsep_proc *,
>                   struct imsg *);
> +void          parent_tls_ticket_rekey_start(struct server *);
> +void          parent_tls_ticket_rekey(int, short, void *);
>  
>  struct httpd                 *httpd_env;
>  
> @@ -252,6 +254,9 @@ main(int argc, char *argv[])
>               exit(0);
>       }
>  
> +     /* initialize the TLS session id to a random key for all procs */
> +     arc4random_buf(env->sc_tls_sid, sizeof(env->sc_tls_sid));
> +
>       if (parent_configure(env) == -1)
>               fatalx("configuration failed");
>  
> @@ -287,6 +292,10 @@ parent_configure(struct httpd *env)
>       TAILQ_FOREACH(srv, env->sc_servers, srv_entry) {
>               if (srv->srv_conf.flags & SRVFLAG_LOCATION)
>                       continue;
> +             /* start the rekey of the tls ticket keys */
> +             if (srv->srv_conf.flags & SRVFLAG_TLS &&
> +                 srv->srv_conf.tls_ticket_lifetime)
> +                     parent_tls_ticket_rekey_start(srv);
>               if (config_setserver(env, srv) == -1)
>                       fatal("send server");
>       }
> @@ -306,6 +315,7 @@ parent_configure(struct httpd *env)
>                       continue;
>               cf.cf_opts = env->sc_opts;
>               cf.cf_flags = env->sc_flags;
> +             memcpy(cf.cf_tls_sid, env->sc_tls_sid, sizeof(cf.cf_tls_sid));
>  
>               proc_compose(env->sc_ps, id, IMSG_CFG_DONE, &cf, sizeof(cf));
>       }
> @@ -449,6 +459,38 @@ parent_dispatch_logger(int fd, struct pr
>       }
>  
>       return (0);
> +}
> +
> +void
> +parent_tls_ticket_rekey_start(struct server *srv)
> +{
> +     struct timeval           tv;
> +
> +     server_generate_ticket_key(&srv->srv_conf);
> +
> +     evtimer_set(&srv->srv_evt, parent_tls_ticket_rekey, srv);
> +     timerclear(&tv);
> +     tv.tv_sec = srv->srv_conf.tls_ticket_lifetime / 4;
> +     evtimer_add(&srv->srv_evt, &tv);
> +}
> +
> +void
> +parent_tls_ticket_rekey(int fd, short events, void *arg)
> +{
> +     struct server           *srv = arg;
> +     struct timeval           tv;
> +
> +     server_generate_ticket_key(&srv->srv_conf);
> +     proc_compose_imsg(httpd_env->sc_ps, PROC_SERVER, -1,
> +         IMSG_TLSTICKET_REKEY, -1, -1, &srv->srv_conf.tls_ticket_key,
> +         sizeof(srv->srv_conf.tls_ticket_key));
> +     explicit_bzero(&srv->srv_conf.tls_ticket_key,
> +         sizeof(srv->srv_conf.tls_ticket_key));
> +
> +     evtimer_set(&srv->srv_evt, parent_tls_ticket_rekey, srv);
> +     timerclear(&tv);
> +     tv.tv_sec = srv->srv_conf.tls_ticket_lifetime / 4;
> +     evtimer_add(&srv->srv_evt, &tv);
>  }
>  
>  /*
> Index: httpd.conf.5
> ===================================================================
> RCS file: /cvs/src/usr.sbin/httpd/httpd.conf.5,v
> retrieving revision 1.80
> diff -u -p -r1.80 httpd.conf.5
> --- httpd.conf.5      16 Mar 2017 10:18:11 -0000      1.80
> +++ httpd.conf.5      24 Mar 2017 07:26:44 -0000
> @@ -564,6 +564,13 @@ will be used (secure protocols; TLSv1.2-
>  Refer to the
>  .Xr tls_config_parse_protocols 3
>  function for other valid protocol string values.
> +.It Ic ticket Ic lifetime Ar seconds
> +Enable TLS session tickets with a
> +.Ar seconds
> +session lifetime.
> +It is possible to set
> +.Ar seconds
> +to default to use the httpd default timeout of 2 hours.
>  .El
>  .El
>  .Sh TYPES
> Index: httpd.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/httpd/httpd.h,v
> retrieving revision 1.130
> diff -u -p -r1.130 httpd.h
> --- httpd.h   7 Feb 2017 12:27:42 -0000       1.130
> +++ httpd.h   16 Feb 2017 19:23:08 -0000
> @@ -76,6 +76,9 @@
>  #define SERVER_MIN_PREFETCHED        32
>  #define SERVER_HSTS_DEFAULT_AGE      31536000
>  #define SERVER_MAX_RANGES    4
> +#define SERVER_DEF_TLS_LIFETIME      (2 * 3600)
> +#define SERVER_MIN_TLS_LIFETIME      (60)
> +#define SERVER_MAX_TLS_LIFETIME      (24 * 3600)
>  
>  #define MEDIATYPE_NAMEMAX    128     /* file name extension */
>  #define MEDIATYPE_TYPEMAX    64      /* length of type/subtype */
> @@ -109,6 +112,7 @@ enum httpchunk {
>  struct ctl_flags {
>       uint8_t          cf_opts;
>       uint32_t         cf_flags;
> +     uint8_t          cf_tls_sid[TLS_MAX_SESSION_ID_LENGTH];
>  };
>  
>  enum key_type {
> @@ -219,7 +223,8 @@ enum imsg_type {
>       IMSG_CFG_DONE,
>       IMSG_LOG_ACCESS,
>       IMSG_LOG_ERROR,
> -     IMSG_LOG_OPEN
> +     IMSG_LOG_OPEN,
> +     IMSG_TLSTICKET_REKEY
>  };
>  
>  enum privsep_procid {
> @@ -444,6 +449,12 @@ struct auth {
>  };
>  TAILQ_HEAD(serverauth, auth);
>  
> +struct server_tls_ticket {
> +     uint32_t        tt_id;
> +     uint32_t        tt_keyrev;
> +     unsigned char   tt_key[TLS_TICKET_KEY_SIZE];
> +};
> +
>  struct server_config {
>       uint32_t                 id;
>       uint32_t                 parent_id;
> @@ -477,6 +488,8 @@ struct server_config {
>       uint8_t                 *tls_ocsp_staple;
>       size_t                   tls_ocsp_staple_len;
>       char                    *tls_ocsp_staple_file;
> +     struct server_tls_ticket tls_ticket_key;
> +     int                      tls_ticket_lifetime;
>  
>       uint32_t                 flags;
>       int                      strip;
> @@ -540,6 +553,8 @@ struct httpd {
>       char                    *sc_chroot;
>       char                    *sc_logdir;
>  
> +     uint8_t                  sc_tls_sid[TLS_MAX_SESSION_ID_LENGTH];
> +
>       struct serverlist       *sc_servers;
>       struct mediatypes       *sc_mediatypes;
>       struct media_type        sc_default_type;
> @@ -573,6 +588,7 @@ void       server(struct privsep *, struct pr
>  int   server_tls_cmp(struct server *, struct server *, int);
>  int   server_tls_load_keypair(struct server *);
>  int   server_tls_load_ocsp(struct server *);
> +void  server_generate_ticket_key(struct server_config *);
>  int   server_privinit(struct server *);
>  void  server_purge(struct server *);
>  void  serverconfig_free(struct server_config *);
> Index: parse.y
> ===================================================================
> RCS file: /cvs/src/usr.sbin/httpd/parse.y,v
> retrieving revision 1.89
> diff -u -p -r1.89 parse.y
> --- parse.y   7 Feb 2017 12:27:42 -0000       1.89
> +++ parse.y   16 Feb 2017 19:20:23 -0000
> @@ -130,10 +130,10 @@ typedef struct {
>  %}
>  
>  %token       ACCESS ALIAS AUTO BACKLOG BODY BUFFER CERTIFICATE CHROOT 
> CIPHERS COMMON> -%token        COMBINED CONNECTION DHE DIRECTORY ECDHE ERR 
> FCGI INDEX IP KEY LISTEN
> -%token       LOCATION LOG LOGDIR MATCH MAXIMUM NO NODELAY OCSP ON PORT 
> PREFORK
> -%token       PROTOCOLS REQUESTS ROOT SACK SERVER SOCKET STRIP STYLE SYSLOG 
> TCP TIMEOUT
> -%token       TLS TYPE TYPES HSTS MAXAGE SUBDOMAINS DEFAULT PRELOAD REQUEST
> +%token       COMBINED CONNECTION DHE DIRECTORY ECDHE ERR FCGI INDEX IP KEY 
> LIFETIME
> +%token       LISTEN LOCATION LOG LOGDIR MATCH MAXIMUM NO NODELAY OCSP ON 
> PORT PREFORK
> +%token       PROTOCOLS REQUESTS ROOT SACK SERVER SOCKET STRIP STYLE SYSLOG 
> TCP TICKET
> +%token       TIMEOUT TLS TYPE TYPES HSTS MAXAGE SUBDOMAINS DEFAULT PRELOAD 
> REQUEST
>  %token       ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP RETURN PASS
>  %token       <v.string>      STRING
>  %token  <v.number>   NUMBER
> @@ -766,6 +766,23 @@ tlsopts          : CERTIFICATE STRING            {
>                       }
>                       free($2);
>               }
> +             | TICKET LIFETIME DEFAULT       {
> +                     srv_conf->tls_ticket_lifetime = SERVER_DEF_TLS_LIFETIME;
> +             }
> +             | TICKET LIFETIME NUMBER        {
> +                     if ($3 != 0 && $3 < SERVER_MIN_TLS_LIFETIME) {
> +                             yyerror("ticket lifetime too small");
> +                             YYERROR;
> +                     }
> +                     if ($3 > SERVER_MAX_TLS_LIFETIME) {
> +                             yyerror("ticket lifetime too large");
> +                             YYERROR;
> +                     }
> +                     srv_conf->tls_ticket_lifetime = $3;
> +             }
> +             | NO TICKET                     {
> +                     srv_conf->tls_ticket_lifetime = 0;
> +             }
>               ;
>  
>  root         : ROOT rootflags
> @@ -1218,6 +1235,7 @@ lookup(char *s)
>               { "index",              INDEX },
>               { "ip",                 IP },
>               { "key",                KEY },
> +             { "lifetime",           LIFETIME },
>               { "listen",             LISTEN },
>               { "location",           LOCATION },
>               { "log",                LOG },
> @@ -1246,6 +1264,7 @@ lookup(char *s)
>               { "subdomains",         SUBDOMAINS },
>               { "syslog",             SYSLOG },
>               { "tcp",                TCP },
> +             { "ticket",             TICKET },
>               { "timeout",            TIMEOUT },
>               { "tls",                TLS },
>               { "type",               TYPE },
> Index: server.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/httpd/server.c,v
> retrieving revision 1.107
> diff -u -p -r1.107 server.c
> --- server.c  7 Feb 2017 12:27:42 -0000       1.107
> +++ server.c  16 Feb 2017 19:20:23 -0000
> @@ -58,6 +58,7 @@ int          server_socket(struct sockaddr_stor
>                   struct server_config *, int, int);
>  int           server_socket_listen(struct sockaddr_storage *, in_port_t,
>                   struct server_config *);
> +struct server        *server_byid(uint32_t);
>  
>  int           server_tls_init(struct server *);
>  void          server_tls_readcb(int, short, void *);
> @@ -135,6 +136,8 @@ server_tls_cmp(struct server *s1, struct
>  
>       if (sc1->tls_protocols != sc2->tls_protocols)
>               return (-1);
> +     if (sc1->tls_ticket_lifetime != sc2->tls_ticket_lifetime)
> +             return (-1);
>       if (strcmp(sc1->tls_ciphers, sc2->tls_ciphers) != 0)
>               return (-1);
>       if (strcmp(sc1->tls_dhe_params, sc2->tls_dhe_params) != 0)
> @@ -266,6 +269,31 @@ server_tls_init(struct server *srv)
>               }
>       }
>  
> +     /* set common session ID among all processes */
> +     if (tls_config_set_session_id(srv->srv_tls_config,
> +         httpd_env->sc_tls_sid, sizeof(httpd_env->sc_tls_sid)) == -1) {
> +             log_warnx("%s: could not set the TLS session ID: %s",
> +                 __func__, tls_config_error(srv->srv_tls_config));
> +             return (-1);
> +     }
> +
> +     /* ticket support */
> +     if (srv->srv_conf.tls_ticket_lifetime) {
> +             if (tls_config_set_session_lifetime(srv->srv_tls_config,
> +                 srv->srv_conf.tls_ticket_lifetime) == -1) {
> +                     log_warnx("%s: could not set the TLS session lifetime: "
> +                         "%s", __func__,
> +                         tls_config_error(srv->srv_tls_config));
> +                     return (-1);
> +             }
> +             tls_config_add_ticket_key(srv->srv_tls_config,
> +                 srv->srv_conf.tls_ticket_key.tt_keyrev,
> +                 srv->srv_conf.tls_ticket_key.tt_key,
> +                 sizeof(srv->srv_conf.tls_ticket_key.tt_key));
> +             explicit_bzero(&srv->srv_conf.tls_ticket_key,
> +                 sizeof(srv->srv_conf.tls_ticket_key));
> +     }
> +
>       if (tls_configure(srv->srv_tls_ctx, srv->srv_tls_config) != 0) {
>               log_warnx("%s: failed to configure tls - %s", __func__,
>                   tls_error(srv->srv_tls_ctx));
> @@ -287,6 +315,16 @@ server_tls_init(struct server *srv)
>  }
>  
>  void
> +server_generate_ticket_key(struct server_config *srv_conf)
> +{
> +     struct server_tls_ticket *key = &srv_conf->tls_ticket_key;
> +
> +     key->tt_id = srv_conf->id;
> +     key->tt_keyrev = arc4random();
> +     arc4random_buf(key->tt_key, sizeof(key->tt_key));
> +}
> +
> +void
>  server_init(struct privsep *ps, struct privsep_proc *p, void *arg)
>  {
>       server_http();
> @@ -438,6 +476,18 @@ serverconfig_byid(uint32_t id)
>       return (NULL);
>  }
>  
> +struct server *
> +server_byid(uint32_t id)
> +{
> +     struct server   *srv;
> +
> +     TAILQ_FOREACH(srv, httpd_env->sc_servers, srv_entry) {
> +             if (srv->srv_conf.id == id)
> +                     return (srv);
> +     }
> +     return (NULL);
> +}
> +
>  int
>  server_foreach(int (*srv_cb)(struct server *,
>      struct server_config *, void *), void *arg)
> @@ -1226,6 +1276,9 @@ server_close(struct client *clt, const c
>  int
>  server_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
>  {
> +     struct server                   *srv;
> +     struct server_tls_ticket         key;
> +
>       switch (imsg->hdr.type) {
>       case IMSG_CFG_MEDIA:
>               config_getmedia(httpd_env, imsg);
> @@ -1247,6 +1300,16 @@ server_dispatch_parent(int fd, struct pr
>               break;
>       case IMSG_CTL_RESET:
>               config_getreset(httpd_env, imsg);
> +             break;
> +     case IMSG_TLSTICKET_REKEY:
> +             IMSG_SIZE_CHECK(imsg, (&key));
> +             memcpy(&key, imsg->data, sizeof(key));
> +             /* apply to the right server */
> +             srv = server_byid(key.tt_id);
> +             if (srv) {
> +                     tls_config_add_ticket_key(srv->srv_tls_config,
> +                         key.tt_keyrev, key.tt_key, sizeof(key.tt_key));
> +             }
>               break;
>       default:
>               return (-1);
> 

-- 

Reply via email to