Claudio Jeker <clau...@openbsd.org> wrote:
> On Tue, Jul 05, 2022 at 10:08:53AM +0000, alex.vatche...@gmail.com wrote:
> > >Synopsis:  httpd+slowcgi sometimes wrongly interpret next request
> > >Category:  daemon
> > >Environment:
> >     System      : OpenBSD 7.1
> >     Details     : OpenBSD 7.1 (GENERIC.MP) #3: Sun May 15 10:27:01 MDT 2022
> >                      
> > r...@syspatch-71-amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP
> > 
> >     Architecture: OpenBSD.amd64
> >     Machine     : amd64
> > >Description:
> >     I've got web application OTOBO which is running on OpenBSD 
> > httpd/slowcgi.
> >     This application heavily uses AJAX.
> >     Sometimes I'm able to reproduce the situation when httpd daemon passes
> >     POST request to OTOBO script (via slowcgi) without POST data.
> >     And the application stops in waiting to it and then times out.
> >     After inspecting source code of httpd I've found the reason:
> >     the http client context is reset after slowcgi closes the connection.
> >     If the connection is not closed (httpd->slowcgi) and the client makes
> >     new request using the same TCP connection (www client -> www server)
> >     it httpd thinks that it already has got the request and headers.

I experienced a similar issue with both slowcgi and gotwebd (a fastcgi
application.)  Can you please try the diff I posted a couple of days
ago on tech@?

Thanks!

https://marc.info/?l=openbsd-tech&m=165986324502568&w=2

diff c183a4a9bb1884f4cdfd8d6387478615af6f7a38 
e159f975f5eeebad1ec6598ba5c76ab7c2eb45bd
commit - c183a4a9bb1884f4cdfd8d6387478615af6f7a38
commit + e159f975f5eeebad1ec6598ba5c76ab7c2eb45bd
blob - 381fade2924c4b5cea77cd9cd6500e75d4d59257
blob + b6541b7c68235ac1dfc5a9d0243db988e5932a7f
--- usr.sbin/httpd/server_fcgi.c
+++ usr.sbin/httpd/server_fcgi.c
@@ -77,6 +77,7 @@ struct server_fcgi_param {
 };
 
 int    server_fcgi_header(struct client *, unsigned int);
+void   server_fcgi_error(struct bufferevent *, short, void *);
 void   server_fcgi_read(struct bufferevent *, void *);
 int    server_fcgi_writeheader(struct client *, struct kv *, void *);
 int    server_fcgi_writechunk(struct client *);
@@ -133,7 +134,7 @@ server_fcgi(struct httpd *env, struct client *clt)
 
        clt->clt_srvbev_throttled = 0;
        clt->clt_srvbev = bufferevent_new(fd, server_fcgi_read,
-           NULL, server_file_error, clt);
+           NULL, server_fcgi_error, clt);
        if (clt->clt_srvbev == NULL) {
                errstr = "failed to allocate fcgi buffer event";
                goto fail;
@@ -482,6 +483,23 @@ fcgi_add_param(struct server_fcgi_param *p, const char
 }
 
 void
+server_fcgi_error(struct bufferevent *bev, short error, void *arg)
+{
+       struct client           *clt = arg;
+
+       if ((error & EVBUFFER_EOF) && !clt->clt_fcgi.headersdone) {
+               server_abort_http(clt, 500, "malformed or no headers");
+               return;
+       }
+
+       /* send the end marker if not already */
+       if (clt->clt_fcgi.chunked && !clt->clt_fcgi.end++)
+               server_bufferevent_print(clt, "0\r\n\r\n");
+
+       server_file_error(bev, error, arg);
+}
+
+void
 server_fcgi_read(struct bufferevent *bev, void *arg)
 {
        uint8_t                          buf[FCGI_RECORD_SIZE];

Reply via email to