Summary: | AJP Connectors fail when POST requests don't have a Content-Length header | ||
---|---|---|---|
Product: | Tomcat Connectors | Reporter: | Bruce G. Stewart <bgstewart> |
Component: | isapi | Assignee: | Tomcat Developers Mailing List <dev> |
Status: | RESOLVED FIXED | ||
Severity: | major | CC: | jfclere |
Priority: | P2 | ||
Version: | 1.2.28 | ||
Target Milestone: | --- | ||
Hardware: | PC | ||
OS: | Windows NT | ||
Attachments: | Read the first body chunk of an APR request that has a Transfer-Encoding header. |
Description
Bruce G. Stewart
2010-02-18 00:34:25 UTC
Are there any chance to see the patch that fixed this for you? Also which mod_jk you are using. Latest stable (1.2.28) should have fixed C-L == 0 issues that can lead to the cross context data corruption. However those fixes mostly address the missing body, not quite all the C-L == 0 cases, so I'd like to see the patch that solves this. Created attachment 25015 [details]
Read the first body chunk of an APR request that has a Transfer-Encoding header.
A proposed patch against tag/TOMCAT_6_0_24 is attached.
OK, So the patch just executes if C-L is zero or not set but T-E is. Seems reasonable. However I'd make sure the T-E is > 0 like we are doing with C-L. If you don't provide a complete patch I'll make something similar in trunk, so we'll see weather it'll get backported, although I see why it shouldn't cause it's not just a nice feature, it's a law :) Thanks I meant T-E == chunked obviously :) Do I miss something: In mod_proxy we have: +++ /* read the first bloc of data */ input_brigade = apr_brigade_create(p, r->connection->bucket_alloc); tenc = apr_table_get(r->headers_in, "Transfer-Encoding"); if (tenc && (strcasecmp(tenc, "chunked") == 0)) { /* The AJP protocol does not want body data yet */ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: request is chunked"); } else { +++ The patch would just block and never get it no? Before putting any fix, the question is if the first body message will be automatically sent (so Jean-Frédéric thinks it is only the case for c-l > 0, from what I understood). All AJP implementations must have the same behavior, otherwise this is big trouble. Right, seems we'll need a descent test case when to issue a read. However the major problem is that read is issued although not a valid AJP sequence (no C-L header) and that should be rejected by the AJP connector instead simply requesting a body chunk from mod_proxy/mod_jk if Servlet thinks this is valid POST request. Are we supporting T-E chunked with the AJP at the first place. Seems to me we don't have any filter inserted inside AJP like we have for HTTP. If not, then T-E=chunked and C-L=0 should be treated as invalid request and connection dropped to prevent any further problems. I am using the ISAPI_Redirect IIS plugin 1.2.28.0 with IIS Version 7. I see there is a separate build that offers "chunking transfer support". Would it solve my problem if I used that without patching Tomcat? Or make things worse? (I should probably go read the source and leave you guys alone.) Thanks for your help and attention. I appreciate it. Isapi chunking is for sending the chunked data. Won't help you there. Anyhow your patch is wrong cause it just hides the symptoms. The real problem is that client EOF is not handled correctly. If the isapi_redirector is not supposed to send the first body block of such a message until it receives a get-body message, then the isapi_redirector must be faulty. On the very first request, and all that follow, the first body block is available on the apr socket immediately after the header is read. With short messages, refillReadBuffer() is never called. With longer ones, the first read picks up a couple of hundred bytes, and refillReadBuffer gets the rest. I haven't seen any problem related to the end of request data being mishandled. Special first body message is only send if C-L is present as this is defined by AJP protocol spec. If it's there without C-L this is faulty and this should be fixed. Can you check with the latest 1.2.29 preview from http://tomcat.apache.org/dev/dist/tomcat-connectors/jk/binaries/win32/jk-1.2.29/ Use the isapi_redirect-1.2.29-dev-911726.dll and rename to isapi_redirect.dll There is also 64-bit version available at http://tomcat.apache.org/dev/dist/tomcat-connectors/jk/binaries/win64/jk-1.2.29/ 1.2.29 has few fixes for tightening the AJP message sequence ordering making it more robust for edge cases. Mladen, isapi_redirect-1.2.29-dev-911726.dll (x64 version) acts just the same way - the first body block is sent right after the header. Browsing the jk code, I see ajp_send_request() in jk_ajp_common.c includes this comment: /* || s->is_chunked - this can't be done here. The original protocol sends the first chunk of post data ( based on Content-Length ), and that's what the java side expects. Sending this data for chunked would break other ajp13 servers. Note that chunking will continue to work - using the normal read. */ but code to test the value of s->is_chunked was removed between revisions 298092 and 298162. Right, it might be the case if IIS sets the ECB->cbTotalBytes Seem we don't check if the C-L is present in that case which might lead to initial post to be send even if the C-L is not present. Give me till Monday and I'll create another snapshot with that issues fixed so we make sure not to send the initial POST packet if there is no C-L header Anyhow can you try with Httpd and see are there any differences since Httpd will not send the first packet. Hope you'll be willing to test it. Changing to PC/NT since it seems only IIS is affected. Also we should probably have IIS/Httpd/Netscape as additional fields for filing the Connector bugs. Please check version isapi_redirect-1.2.29-dev-912307.dll from http://tomcat.apache.org/dev/dist/tomcat-connectors/jk/binaries/win64/jk-1.2.29/amd64/ It should have resolved initial POST data for T-E being send. IIS sets 0xFFFFFFFF for cbTotalBytes which we were using for content-length but this value means "Unknown body size". This should also solve the posts larger then 4Gb We are waiting on your input for making a final 1.2.29 :) isapi_redirect-1.2.29-dev-912307.dll solves my issue. (I saw the C-L -1 in the ajp messages to Tomcat, but since Tomcat looked for C-L > 0, I assumed that -1 was intentional. Sorry I didn't mention it - might have saved you some digging.) Thank you very much. This is actually very important. Tomcat looks for C-L > 0 but inside JK we were just looking for C-L != 0 and send the initial packet after the request. Also we use 64-bits for C-L thus 0xFFFFFFFF mean 4Gb. Now if the servlet didn't consume that packet there was a chance it get interpreted as a new request. If it looked as a normal request things could get pretty nasty. The next request could receive the data from the previous request. With the current fix instead sending that value we don't send the C-L at all which according to the AJP spec mean "unknow". This morning, I had some failures of another application using the .29 dll and the same Tomcat. I haven't yet determined if this is a misconfiguration issue or a bug, but I thought I should show it to you: [Mon Feb 22 08:13:50.104 2010] [4320:3432] [info] init_jk::jk_isapi_plugin.c (2403): Starting Jakarta/ISAPI/isapi_redirector/1.2.29-dev-912307 [Mon Feb 22 08:13:50.151 2010] [4320:3432] [info] init_jk::jk_isapi_plugin.c (2573): Jakarta/ISAPI/isapi_redirector/1.2.29-dev-912307 initialized [Mon Feb 22 08:13:57.530 2010] [4320:3432] [error] ajp_connection_tcp_get_message::jk_ajp_common.c (1264): wrong message size 8196 8192 from 127.0.0.1:8009 [Mon Feb 22 08:13:57.530 2010] [4320:1896] [error] ajp_connection_tcp_get_message::jk_ajp_common.c (1264): wrong message size 8196 8192 from 127.0.0.1:8009 [Mon Feb 22 08:13:57.546 2010] [4320:3432] [error] ajp_get_reply::jk_ajp_common.c (2072): (ajp13w) Tomcat is down or network problems. Part of the response has already been sent to the client [... more of the same, and eventually ...] [Mon Feb 22 08:13:58.107 2010] [4320:3432] [info] service::jk_lb_worker.c (1464): All tomcat instances are busy or in error state [Mon Feb 22 08:13:58.107 2010] [4320:3432] [error] service::jk_lb_worker.c (1469): All tomcat instances failed, no more workers left > ajp_connection_tcp_get_message::jk_ajp_common.c (1264): wrong message size 8196
This looks like mismatch in maxPacketSize. Seems the Tomcat is configured
for larger then default packet sizes.
Will be part of 1.2.29. |