On Wed, 21 Oct 2026 16:09:28 +0200,
Rafael Sadowski <[email protected]> wrote:
> 
> On Wed Oct 21, 2026 at 09:24:42AM +0200, Rafael Sadowski wrote:
> > On Tue Oct 20, 2026 at 05:35:53PM -0700, James J. Lippard wrote:
> > > I have multiple servers listening on the same host and port and using
> > > "ticket lifetime default" in their tls config blocks.  Now httpd
> > > crashes out on the first ticket rekey with:
> > > 
> > > httpd[6452]: fatal in server: proc_dispatch: server 2 got invalid imsg 23 
> > > peerid -1 from parent 1
> > > 
> > > The parent starts a rekey timer for every non-location TLS server
> > > block and sends IMSG_TLSTICKET_REKEY with that block's id. In the
> > > server processes, blocks sharing a socket are merged, the first
> > > becomes the struct server and the rest are attached as srv_hosts.
> > > server_byid() only searches the top-level servers, so the rekey for
> > > any merged block finds nothing.  In OpenBSD 7.9 those misses were
> > > ignored:
> > > 
> > >           srv = server_byid(key.tt_id);
> > >           if (srv) {
> > >                   tls_config_add_ticket_key(...);
> > >           }
> > > 
> > > but in 8.0 it returns -1 which proc_dispatch() reports as "invalid imsg"
> > > and turns into fatalx().  Using -vv the line before the fatal is
> > > the "invalid sever id" (typo in source) message; here's a patch that
> > > makes it non-fatal again":
> > > 
> > > Index: usr.sbin/httpd/server.c
> > > ===================================================================
> > > RCS file: /cvs/src/usr.sbin/httpd/server.c,v
> > > diff -u -p -r1.143 server.c
> > > --- usr.sbin/httpd/server.c       15 Oct 2026 10:59:00 -0000      1.143
> > > +++ usr.sbin/httpd/server.c       20 Oct 2026 00:00:00 -0000
> > > @@ -1425,8 +1425,14 @@ server_dispatch_parent(int fd, struct pr
> > >           memcpy(&key, imsg->data, sizeof(key));
> > >           /* apply to the right server */
> > >           if ((srv = server_byid(key.tt_id)) == NULL) {
> > > -                 log_debug("%s: invalid sever id", __func__);
> > > -                 return (-1);
> > > +                 /*
> > > +                  * Not a listening server, but a name-based host
> > > +                  * merged onto another server's socket; their shared
> > > +                  * TLS context is rekeyed via the listening server.
> > > +                  */
> > > +                 log_debug("%s: ignoring rekey for server id %u",
> > > +                     __func__, key.tt_id);
> > > +                 break;
> > >           }
> > >           if (tls_config_add_ticket_key(srv->srv_tls_config,
> > >               key.tt_keyrev, key.tt_key, sizeof(key.tt_key)) == -1) {
> > 
> > Hi James,
> > 
> > thanks for the report and the patch.
> > 
> > I think the stricter imsg handling in 8.0 found a real problem. The TLS
> > config is per socket, not per server block. Only the first server on a
> > socket sets up the tls_config. For the other virtual servers only the
> > cert/key (for SNI) is used, so their "ticket lifetime" has no effect.
> > 
> > This also means: if the first server has no ticket lifetime but a later
> > one has, tickets are disabled for the whole socket, without any warning.
> > Welcome to the httpd.conf/parse.y madness where everything is valid!
> > 
> > So I would do this in two steps:
> > 
> > 1) Replace the return (-1) with your patch, so httpd does not crash.
> > 
> > 2) Make the config stricter: warn (or fail) in parse.y if servers on
> >    the same socket have different TLS settings, start rekey timers only
> >    for the listening server, and document in httpd.conf(5) that these
> >    TLS options apply per socket.
> > 
> > kirill@ are you ok with this?
> > 
> > Rafael
> > 
> 
> "Small" correction to my last mail: parse.y already rejects different
> ticket settings on the same address/port, so no new check is needed there.
> I blame this one too often!
> 
> I think the better fix is in the parent. It starts a rekey timer for
> every TLS server, but only the first server on an address/port gets a
> struct server in the server processes. The diff below starts the timer
> ONLY for that one.
> 
> Tested with two TLS servers on the same socket: the "ignoring rekey"
> messages from James' diff are gone. What I believe is the right
> solution.
> 
> It annoys me that this bug made it into version 8.0, but the problem
> actually reveals the real flaw.
> 
> OK?
>

ok Kirill@

> diff --git a/httpd.c b/httpd.c
> index abfbb5c..6ca2e24 100644
> --- a/httpd.c
> +++ b/httpd.c
> @@ -298,7 +298,8 @@ parent_configure(struct httpd *env)
>                       continue;
>               /* start the rekey of the tls ticket keys */
>               if (srv->srv_conf.flags & SRVFLAG_TLS &&
> -                 srv->srv_conf.tls_ticket_lifetime)
> +                 srv->srv_conf.tls_ticket_lifetime &&
> +                 server_match(srv, 0) == srv)
>                       parent_tls_ticket_rekey_start(srv);
>               if (config_setserver(env, srv) == -1)
>                       fatal("send server");
> 

-- 
wbr, Kirill

Reply via email to