You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Jim Jagielski <ji...@jaguNET.com> on 2002/07/06 23:00:38 UTC
[PATCH] Making the protocol check runtime
This is not the complete patch, but implements the logic of the
protocol check... This also avoids the use of '%n' for sscanf and
instead uses a nice little trick.
Comments? If this looks good, I'll add the remaining bits (like the
directive) and commit.
Index: src/main/http_protocol.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_protocol.c,v
retrieving revision 1.322
diff -u -r1.322 http_protocol.c
--- src/main/http_protocol.c 26 Jun 2002 18:34:00 -0000 1.322
+++ src/main/http_protocol.c 6 Jul 2002 20:55:42 -0000
@@ -991,7 +991,9 @@
const char *uri;
conn_rec *conn = r->connection;
unsigned int major = 1, minor = 0; /* Assume HTTP/1.0 if non-"HTTP" protocol */
- int len, n = 0;
+ int len = 0;
+ int valid_protocol = 1;
+ char *kruft;
/* Read past empty lines until we get a real request line,
* a read error, the connection closes (EOF), or we timeout.
@@ -1053,26 +1055,41 @@
r->assbackwards = (ll[0] == '\0');
r->protocol = ap_pstrdup(r->pool, ll[0] ? ll : "HTTP/0.9");
- if (2 == sscanf(r->protocol, "HTTP/%u.%u%n", &major, &minor, &n)
- && minor < HTTP_VERSION(1,0)) /* don't allow HTTP/0.1000 */
- r->proto_num = HTTP_VERSION(major, minor);
+ /* Avoid sscanf in the common case */
+ if (strlen(r->protocol) == 8
+ && r->protocol[0] == 'H' && r->protocol[1] == 'T'
+ && r->protocol[2] == 'T' && r->protocol[3] == 'P'
+ && r->protocol[4] == '/' && ap_isdigit(r->protocol[5])
+ && r->protocol[6] == '.' && ap_isdigit(r->protocol[7])) {
+ r->proto_num = HTTP_VERSION(r->protocol[5] - '0', r->protocol[7] - '0');
+ }
else {
- r->proto_num = HTTP_VERSION(1,0);
- n = 0;
+ kruft = ap_palloc(r->pool, strlen(r->protocol)+1);
+ if (2 == sscanf(r->protocol, "HTTP/%u.%u%s", &major, &minor, kruft)
+ && minor < HTTP_VERSION(1,0)) /* don't allow HTTP/0.1000 */
+ r->proto_num = HTTP_VERSION(major, minor);
+ else {
+ r->proto_num = HTTP_VERSION(1,0);
+ valid_protocol = 0;
+ }
}
/* Check for a valid protocol, and disallow everything but whitespace
- * after the protocol string */
- while (ap_isspace(r->protocol[n]))
- ++n;
- if (r->protocol[n] != '\0') {
- r->status = HTTP_BAD_REQUEST;
- r->proto_num = HTTP_VERSION(1,0);
- r->protocol = ap_pstrdup(r->pool, "HTTP/1.0");
- ap_table_setn(r->notes, "error-notes",
- "The request line contained invalid characters "
- "following the protocol string.<P>\n");
- return 0;
+ * after the protocol string. A protocol string of nothing but
+ * whitespace is considered valid */
+ if (ap_protocol_req_check && !valid_protocol) {
+ int n = 0;
+ while (ap_isspace(r->protocol[n]))
+ ++n;
+ if (r->protocol[n] != '\0') {
+ r->status = HTTP_BAD_REQUEST;
+ r->proto_num = HTTP_VERSION(1,0);
+ r->protocol = ap_pstrdup(r->pool, "HTTP/1.0");
+ ap_table_setn(r->notes, "error-notes",
+ "The request line contained invalid characters "
+ "following the protocol string.<P>\n");
+ return 0;
+ }
}
return 1;
--
===========================================================================
Jim Jagielski [|] jim@jaguNET.com [|] http://www.jaguNET.com/
"A society that will trade a little liberty for a little order
will lose both and deserve neither" - T.Jefferson