Bug #2197

lighttpd stalls when reading fragmented ssl requests

Added by andreas_stoe over 4 years ago. Updated over 4 years ago.

Status:FixedStart date:2010-05-11
Priority:HighDue date:
Assignee:-% Done:

100%

Category:core
Target version:1.4.27
Missing in 1.5.x:No

Description

Hello.

Since switching from lighttpd 1.4.22 to lighttpd 1.4.26, lighttpd sometimes doesn't respond to some requests, which results in the browser showing only a white page and getting a timeout after a certain time.

After some investigations I found out that lighttpd doesn't even handle the request and hangs in the "READ" state, waiting for more header lines to arrive:

2010-05-11 13:23:09: (log.c.166) server started 
2010-05-11 13:23:10: (connections.c.1372) state at start 6 req-start 
2010-05-11 13:23:10: (connections.c.1384) state for fd 6 req-start 
2010-05-11 13:23:10: (connections.c.1635) state for fd 6 read 
2010-05-11 13:23:10: (connections.c.1778) state at exit: 6 read 
2010-05-11 13:23:10: (connections.c.1372) state at start 6 read 
2010-05-11 13:23:10: (connections.c.1635) state for fd 6 read 
2010-05-11 13:23:10: (connections.c.1778) state at exit: 6 read 
2010-05-11 13:23:10: (connections.c.1372) state at start 6 read 
2010-05-11 13:23:10: (connections.c.1635) state for fd 6 read 
2010-05-11 13:23:10: (connections.c.1778) state at exit: 6 read 
2010-05-11 13:23:10: (connections.c.1372) state at start 6 read 
2010-05-11 13:23:10: (connections.c.1635) state for fd 6 read 
2010-05-11 13:23:10: (connections.c.1778) state at exit: 6 read 
2010-05-11 13:23:10: (connections.c.1372) state at start 6 read 
2010-05-11 13:23:10: (connections.c.1635) state for fd 6 read 
2010-05-11 13:23:10: (connections.c.1778) state at exit: 6 read 

The problem can be relatively simple reproduced using the newest lighttpd-checkout (revision 2724) independently of the OpenSSL version. When sending a HTTP request header within a single packet, everything works fine, when sending each header line independently, the webserver stops to respond.

The following CLI-PHP code is able to evoke the problem:

<?php
//If data gets send in the intermediate mode, lighttpd doesn't response when using SSL
define(INTERMEDIATE, true);

function write_socket($sock, $line, &$request)
{
    $request .= $line;
    if (INTERMEDIATE)
        write_socket_flush($sock, $request);
}

function write_socket_flush($sock, &$request)
{
    fwrite($sock, $request);
    $request = '';
}

$sock = fsockopen("ssl://10.44.44.63", 443);
if ($sock)
{
    echo("Sending request\n");

    $request = "";
    write_socket($sock, "GET / HTTP/1.1\r\n", $request);
    write_socket($sock, "Host: 10.44.44.63\r\n", $request);
    write_socket($sock, "Connection: close\r\n", $request);
    write_socket($sock, "\r\n", $request);

    if (!INTERMEDIATE)
        write_socket_flush($sock, $request);

    echo("Listening\n");
    $response = "";
    while (!feof($sock))
    {
        $response .= fread($sock, 2048);
    }

    echo($response);

    fclose($sock);
}

Summary:
Responding to headers which are fragmented across multiple TCP-Packets doesn't work on a SSL connection in the in 1.4.26 and in the 1.4.x checkout. It worked until version 1.4.25.

Thanks,
Andreas

Fix-stalls-while-reading-from-ssl-sockets-fixes-2197.patch Magnifier (2.2 KB) stbuehler, 2010-05-23 14:03


Related issues

Duplicated by Bug #607: lighttpd + mod_ssl stalls on POST requests between 8317 a... Duplicate

Associated revisions

Revision 2729
Added by stbuehler over 4 years ago

Fix stalls while reading from ssl sockets (fixes #2197)

History

#1 Updated by andreas_stoe over 4 years ago

  • % Done changed from 0 to 50

I found out that there was one change in connections.c which appeared strange to me: In connection_handle_read_ssl:235 (revision 2724) you wrote

    } while (len == toread && count < MAX_READ_LIMIT);

This actually makes no sense (to me): len is set to the count of bytes that have been read from the SSL socket and toread is the count of bytes which was ought to be read, wheras toread may be restricted to the count of bytes available in the current read buffer. As this value might be smaller than the actual bytes pending on the SSL socket, len == toread doesn't say anything about whether all data has been read from the socket.

The line

    } while (len > 0 && count < MAX_READ_LIMIT);

from version 1.4.25 made more sense to me, as data is read from the SSL-Socket until SSL_read returns an error or no data is available.

Please inform me, whether my "fix" makes sense or whether this destroys any feature I've been too blind to see.

Andreas

PS: I forgot to mention explicitly, that this small patch fixes the problem described above.

#2 Updated by stbuehler over 4 years ago

The idea is, that if one read resulted in less bytes than possible the internal ssl buffer should be empty; we don't care whether the kernel buffer is "empty", as we get another fdevent in that case and can continue to read later.

But i guess it looks like this doesn't work.

#4 Updated by stbuehler over 4 years ago

  • Status changed from New to Fixed
  • % Done changed from 50 to 100

Applied in changeset r2729.

Also available in: Atom