Alexander Bluhm(alexander.bl...@gmx.net) on 2017.09.22 19:54:56 +0200:
> Hi,
> 
> The relayd regression tests for chunked http traffic fail sometimes.
> Ktrace reveals that this happens when the \r and \n at the end of
> a header line are read in separate chunks.  Then evbuffer_readline()
> interpretes the \r as the end of the first line and the \n as an
> additional empty line.  So relayd gets out of sync with the http
> protocol.
> 
> The function evbuffer_readln() has been added with libevent 1.4.13
> in 2010.  With the parameter EVBUFFER_EOL_CRLF the parsing works
> reliably.
> 
> ok?

looks good, ok benno@
 
> bluhm
> 
> Index: usr.sbin/relayd/relay.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/relay.c,v
> retrieving revision 1.226
> diff -u -p -r1.226 relay.c
> --- usr.sbin/relayd/relay.c   28 Aug 2017 17:31:00 -0000      1.226
> +++ usr.sbin/relayd/relay.c   22 Sep 2017 16:50:51 -0000
> @@ -1679,8 +1679,10 @@ relay_close(struct rsession *con, const 
>               (void)print_host(&con->se_in.ss, ibuf, sizeof(ibuf));
>               (void)print_host(&con->se_out.ss, obuf, sizeof(obuf));
>               if (EVBUFFER_LENGTH(con->se_log) &&
> -                 evbuffer_add_printf(con->se_log, "\r\n") != -1)
> -                     ptr = evbuffer_readline(con->se_log);
> +                 evbuffer_add_printf(con->se_log, "\r\n") != -1) {
> +                     ptr = evbuffer_readln(con->se_log, NULL,
> +                         EVBUFFER_EOL_CRLF);
> +             }
>               log_info("relay %s, "
>                   "session %d (%d active), %s, %s -> %s:%d, "
>                   "%s%s%s", rlay->rl_conf.name, con->se_id, relay_sessions,
> Index: usr.sbin/relayd/relay_http.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/relay_http.c,v
> retrieving revision 1.66
> diff -u -p -r1.66 relay_http.c
> --- usr.sbin/relayd/relay_http.c      28 May 2017 10:39:15 -0000      1.66
> +++ usr.sbin/relayd/relay_http.c      22 Sep 2017 16:44:05 -0000
> @@ -169,14 +169,16 @@ relay_read_http(struct bufferevent *bev,
>               goto done;
>       }
>  
> -     while (!cre->done && (line = evbuffer_readline(src)) != NULL) {
> -             linelen = strlen(line);
> +     while (!cre->done) {
> +             line = evbuffer_readln(src, &linelen, EVBUFFER_EOL_CRLF);
> +             if (line == NULL)
> +                     break;
>  
>               /*
>                * An empty line indicates the end of the request.
>                * libevent already stripped the \r\n for us.
>                */
> -             if (!linelen) {
> +             if (linelen == 0) {
>                       cre->done = 1;
>                       free(line);
>                       break;
> @@ -594,7 +596,7 @@ relay_read_httpchunks(struct bufferevent
>       struct evbuffer         *src = EVBUFFER_INPUT(bev);
>       char                    *line;
>       long long                llval;
> -     size_t                   size;
> +     size_t                   size, linelen;
>  
>       getmonotime(&con->se_tv_last);
>       cre->timedout = 0;
> @@ -625,13 +627,13 @@ relay_read_httpchunks(struct bufferevent
>       }
>       switch (cre->toread) {
>       case TOREAD_HTTP_CHUNK_LENGTH:
> -             line = evbuffer_readline(src);
> +             line = evbuffer_readln(src, &linelen, EVBUFFER_EOL_CRLF);
>               if (line == NULL) {
>                       /* Ignore empty line, continue */
>                       bufferevent_enable(bev, EV_READ);
>                       return;
>               }
> -             if (strlen(line) == 0) {
> +             if (linelen == 0) {
>                       free(line);
>                       goto next;
>               }
> @@ -660,7 +662,7 @@ relay_read_httpchunks(struct bufferevent
>               break;
>       case TOREAD_HTTP_CHUNK_TRAILER:
>               /* Last chunk is 0 bytes followed by trailer and empty line */
> -             line = evbuffer_readline(src);
> +             line = evbuffer_readln(src, &linelen, EVBUFFER_EOL_CRLF);
>               if (line == NULL) {
>                       /* Ignore empty line, continue */
>                       bufferevent_enable(bev, EV_READ);
> @@ -671,7 +673,7 @@ relay_read_httpchunks(struct bufferevent
>                       free(line);
>                       goto fail;
>               }
> -             if (strlen(line) == 0) {
> +             if (linelen == 0) {
>                       /* Switch to HTTP header mode */
>                       cre->toread = TOREAD_HTTP_HEADER;
>                       bev->readcb = relay_read_http;
> @@ -680,7 +682,7 @@ relay_read_httpchunks(struct bufferevent
>               break;
>       case 0:
>               /* Chunk is terminated by an empty newline */
> -             line = evbuffer_readline(src);
> +             line = evbuffer_readln(src, &linelen, EVBUFFER_EOL_CRLF);
>               free(line);
>               if (relay_bufferevent_print(cre->dst, "\r\n") == -1)
>                       goto fail;
> 

Reply via email to