DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=13869>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=13869

mod_jk2 becomes confused when client breaks the connection

           Summary: mod_jk2 becomes confused when client breaks the
                    connection
           Product: Tomcat 4
           Version: 4.1.12
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: Blocker
          Priority: Other
         Component: Connector:Coyote JK 2
        AssignedTo: [EMAIL PROTECTED]
        ReportedBy: [EMAIL PROTECTED]


When the connection between mod_jk2 and a client browser gets interrupted, e.g.
because the client closed the connection, the communication link between mod_jk2
and tomcat gets into an illegal state. mod_jk2 will send the remaining part of
tomcats response to some other client, e.g., clients will receive (parts of)
responses to requests they have not sent. Users may consequently slip into
sessions of other user. Note that besides of the fact the users' requests are
not served the right way this is a major security issue. Once this happend the
server becomes largely unusable until it is shutdown and restarted.

Reproducing the problem is somewhat tricky. You have to cut the connection at
the right time. The script below tries to read parts of varying size before it
closes the connection to increase the likelyhood that it eventually hits the
right time. On the systems I have tried the error will occure almost instantly,
but that might not be the case on your system. Here is the script:

----------------------------------------------------------------
#!/usr/bin/perl -w

use Socket;

##################################################
# adjust this to your tomcat / apache installation
$host = "localhost";
$port = 9600;
$doc = "/erfx/const.jsp";
##################################################

$count = 0;
$read_lines = 1;

sub request {
    my ($doc) = @_;
start:
    $count++;
    my $iaddr = inet_aton($host)
        or die "unknown host\n";
    my $paddr = sockaddr_in($port, $iaddr);
    my $proto = getprotobyname('tcp');

    socket(SOCK, PF_INET, SOCK_STREAM, $proto)
        or die "socket failed\n";
    connect(SOCK, $paddr)
        or die "connect failed\n";
    select SOCK;
    $| = 1;
    select STDOUT;

    print SOCK <<END
GET $doc HTTP/1.0\r
User-Agent: test\r
Host: $host\r
\r
END
    ;

    my $result = "";
    while(<SOCK>) {
        if ($count % 2 == 0 && $read_lines == $.) {
            $read_lines = 1 + ($read_lines + 1) % 20;
            close(SOCK);
            goto start;
        }
        $result .= $_;
    }

    close(SOCK);

    return $result;
}


$result = request $doc;

$result =~ /value:\s*(\d+)(.|[\n\r])*href=\"([^\"]+)\"/m
    or die "$result\nBad response\n";
$value = $1;
$url = $3;

print "$value $url\n";

$|=1;
for ($i = 0; ; $i++) {
    $result = request $url;
    $result =~ /value:\s*(\d+)(.|[\n\r])*href=\"([^\"]+)\"/m
        or die "$result\nBad response\n"    ;
    $my_value = $1;
    $my_url = $3;
    $my_url eq $url or die "Got wrong URL: $my_url $url\n";
    $my_value eq $value or die "Got wrong value: $my_value $value\n";
    print "$i ok\r";
}
</pre>
----------------------------------------------------------------

and the test JSP the script requests:

----------------------------------------------------------------
<html>
<head><title>Test Page</title></head>
<body>
<p>HI THERE!</p>
<jsp:useBean id="date" scope="session" class="java.util.Date"/>
<p>value: <jsp:getProperty name="date" property="time"/></p>
<p><a href="<%= response.encodeURL(request.getRequestURI()) %>">again</a></p>
<% for (int y = 0; y < 50; y++) { %>
<p>
<% for (int i = 0; i < 1000; i++) { %> test <% } %>
<p>
<% } %>
</body>
</html>
----------------------------------------------------------------

Put that somewhere into your installation and adjust the marked lines in the
script to point to the right location.

The script might detect the error different ways. Usually it will fail with "Bad
response" because it receives the remaining part of a terminated response
missing the lines at the beginning the script looks for. May may also try
running multiple instances of the script. You may then get parts of responses to
requests of another instance.

The following patch provides a simple fix for the problem:

----------------------------------------------------------------
-- jk/native2/common/jk_worker_ajp13.c_old     2002-10-23 06:42:33.000000000 +0200
+++ jk/native2/common/jk_worker_ajp13.c 2002-10-23 06:29:48.000000000 +0200
@@ -394,6 +394,7 @@
          * upload data and we must consider that operation is no more recoverable
          */
         if (err!=JK_OK && ! e->recoverable ) {
+           e->worker->in_error_state=JK_TRUE;
             s->is_recoverable_error = JK_FALSE;
             env->l->jkLog(env, env->l, JK_LOG_ERROR,
                           "ajp13.service() ajpGetReply unrecoverable error %d\n",
----------------------------------------------------------------

This way mod_jk2 will close the connection to tomcat and reconnect, thereby
dumping the part of tomcats response which can no longer be forwarded to the
client. Note: I did not look much at the AJP13 protocol and the sources. There
may be better ways to fix this.

--
To unsubscribe, e-mail:   <mailto:tomcat-dev-unsubscribe@;jakarta.apache.org>
For additional commands, e-mail: <mailto:tomcat-dev-help@;jakarta.apache.org>

Reply via email to