mirror of https://github.com/fafhrd91/actix-web
Merge commit from fork
This commit is contained in:
parent
e6d09913d9
commit
3c056bd361
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
- Reject HTTP/1 requests with ambiguous request framing from `Content-Length` and `Transfer-Encoding` headers to prevent request smuggling.
|
||||||
- Encode the HTTP/1 `Connection: Upgrade` header in Camel-Case when camel-case header formatting is enabled.[#3953]
|
- Encode the HTTP/1 `Connection: Upgrade` header in Camel-Case when camel-case header formatting is enabled.[#3953]
|
||||||
- Fix `HeaderMap` iterators' `len()` and `size_hint()` implementations for multi-value headers.
|
- Fix `HeaderMap` iterators' `len()` and `size_hint()` implementations for multi-value headers.
|
||||||
- Update `rand` dependency to `0.10`.
|
- Update `rand` dependency to `0.10`.
|
||||||
|
|
|
||||||
|
|
@ -237,4 +237,18 @@ mod tests {
|
||||||
assert_eq!(*req.method(), Method::POST);
|
assert_eq!(*req.method(), Method::POST);
|
||||||
assert!(req.chunked().unwrap());
|
assert!(req.chunked().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn test_http_request_rejects_content_length_and_chunked() {
|
||||||
|
let mut codec = Codec::default();
|
||||||
|
let mut buf = BytesMut::from(
|
||||||
|
"POST /test HTTP/1.1\r\n\
|
||||||
|
content-length: 11\r\n\
|
||||||
|
transfer-encoding: chunked\r\n\r\n\
|
||||||
|
0\r\n\r\n\
|
||||||
|
GET /test2 HTTP/1.1\r\n\r\n",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(codec.decode(&mut buf).is_err());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -275,6 +275,23 @@ impl MessageType for Request {
|
||||||
// convert headers
|
// convert headers
|
||||||
let mut length = msg.set_headers(&src.split_to(len).freeze(), &headers[..h_len], ver)?;
|
let mut length = msg.set_headers(&src.split_to(len).freeze(), &headers[..h_len], ver)?;
|
||||||
|
|
||||||
|
if msg.head().headers.contains_key(header::TRANSFER_ENCODING) {
|
||||||
|
if ver == Version::HTTP_10 {
|
||||||
|
debug!("Transfer-Encoding is not allowed in HTTP/1.0 requests");
|
||||||
|
return Err(ParseError::Header);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !crate::HttpMessage::chunked(&msg)? {
|
||||||
|
debug!("request Transfer-Encoding must be chunked");
|
||||||
|
return Err(ParseError::Header);
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg.head().headers.contains_key(header::CONTENT_LENGTH) {
|
||||||
|
debug!("both Content-Length and Transfer-Encoding are set");
|
||||||
|
return Err(ParseError::Header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// disallow HTTP/1.0 POST requests that do not contain a Content-Length headers
|
// disallow HTTP/1.0 POST requests that do not contain a Content-Length headers
|
||||||
// see https://datatracker.ietf.org/doc/html/rfc1945#section-7.2.2
|
// see https://datatracker.ietf.org/doc/html/rfc1945#section-7.2.2
|
||||||
if ver == Version::HTTP_10 && method == Method::POST && length.is_none() {
|
if ver == Version::HTTP_10 && method == Method::POST && length.is_none() {
|
||||||
|
|
@ -1116,18 +1133,57 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn hrs_cl_and_te_http10() {
|
fn hrs_cl_and_te_http10() {
|
||||||
// in HTTP/1.0 transfer encoding is simply ignored so it's fine to have both
|
expect_parse_err!(&mut BytesMut::from(
|
||||||
|
|
||||||
let mut buf = BytesMut::from(
|
|
||||||
"GET / HTTP/1.0\r\n\
|
"GET / HTTP/1.0\r\n\
|
||||||
Host: example.com\r\n\
|
Host: example.com\r\n\
|
||||||
Content-Length: 3\r\n\
|
Content-Length: 3\r\n\
|
||||||
Transfer-Encoding: chunked\r\n\
|
Transfer-Encoding: chunked\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
000",
|
000",
|
||||||
);
|
));
|
||||||
|
}
|
||||||
|
|
||||||
parse_ready!(&mut buf);
|
#[test]
|
||||||
|
fn hrs_cl_and_chunked_te_http11() {
|
||||||
|
expect_parse_err!(&mut BytesMut::from(
|
||||||
|
"POST / HTTP/1.1\r\n\
|
||||||
|
Host: example.com\r\n\
|
||||||
|
Content-Length: 3\r\n\
|
||||||
|
Transfer-Encoding: chunked\r\n\
|
||||||
|
\r\n\
|
||||||
|
0\r\n\
|
||||||
|
\r\n",
|
||||||
|
));
|
||||||
|
|
||||||
|
expect_parse_err!(&mut BytesMut::from(
|
||||||
|
"POST / HTTP/1.1\r\n\
|
||||||
|
Host: example.com\r\n\
|
||||||
|
Transfer-Encoding: chunked\r\n\
|
||||||
|
Content-Length: 3\r\n\
|
||||||
|
\r\n\
|
||||||
|
0\r\n\
|
||||||
|
\r\n",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hrs_identity_te_http11() {
|
||||||
|
expect_parse_err!(&mut BytesMut::from(
|
||||||
|
"POST / HTTP/1.1\r\n\
|
||||||
|
Host: example.com\r\n\
|
||||||
|
Transfer-Encoding: identity\r\n\
|
||||||
|
\r\n\
|
||||||
|
0\r\n",
|
||||||
|
));
|
||||||
|
|
||||||
|
expect_parse_err!(&mut BytesMut::from(
|
||||||
|
"POST / HTTP/1.1\r\n\
|
||||||
|
Host: example.com\r\n\
|
||||||
|
Content-Length: 3\r\n\
|
||||||
|
Transfer-Encoding: identity\r\n\
|
||||||
|
\r\n\
|
||||||
|
0\r\n",
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -1165,14 +1221,16 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn transfer_encoding_agrees() {
|
fn hrs_chunked_te_http11() {
|
||||||
let mut buf = BytesMut::from(
|
let mut buf = BytesMut::from(
|
||||||
"GET /test HTTP/1.1\r\n\
|
"GET /test HTTP/1.1\r\n\
|
||||||
Host: example.com\r\n\
|
Host: example.com\r\n\
|
||||||
Content-Length: 3\r\n\
|
Transfer-Encoding: chunked\r\n\
|
||||||
Transfer-Encoding: identity\r\n\
|
|
||||||
\r\n\
|
\r\n\
|
||||||
0\r\n",
|
1\r\n\
|
||||||
|
a\r\n\
|
||||||
|
0\r\n\
|
||||||
|
\r\n",
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut reader = MessageDecoder::<Request>::default();
|
let mut reader = MessageDecoder::<Request>::default();
|
||||||
|
|
@ -1180,6 +1238,6 @@ mod tests {
|
||||||
let mut pl = pl.unwrap();
|
let mut pl = pl.unwrap();
|
||||||
|
|
||||||
let chunk = pl.decode(&mut buf).unwrap().unwrap();
|
let chunk = pl.decode(&mut buf).unwrap().unwrap();
|
||||||
assert_eq!(chunk, PayloadItem::Chunk(Bytes::from_static(b"0\r\n")));
|
assert_eq!(chunk, PayloadItem::Chunk(Bytes::from_static(b"a")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue