Browse Source

Reject absolute URIs with no authority components

Loïc Hoguin 7 years ago
parent
commit
8d9404e9b6
1 changed files with 14 additions and 8 deletions
  1. 14 8
      src/cowboy_http.erl

+ 14 - 8
src/cowboy_http.erl

@@ -379,28 +379,34 @@ parse_method(<< C, Rest/bits >>, State, SoFar, Remaining) ->
 parse_uri(<< H, T, T, P, "://", Rest/bits >>, State, Method)
 parse_uri(<< H, T, T, P, "://", Rest/bits >>, State, Method)
 		when H =:= $h orelse H =:= $H, T =:= $t orelse T =:= $T;
 		when H =:= $h orelse H =:= $H, T =:= $t orelse T =:= $T;
 			P =:= $p orelse P =:= $P ->
 			P =:= $p orelse P =:= $P ->
-	parse_uri_skip_host(Rest, State, Method);
+	parse_uri_skip_host(Rest, State, Method, <<>>);
 parse_uri(<< H, T, T, P, S, "://", Rest/bits >>, State, Method)
 parse_uri(<< H, T, T, P, S, "://", Rest/bits >>, State, Method)
 		when H =:= $h orelse H =:= $H, T =:= $t orelse T =:= $T;
 		when H =:= $h orelse H =:= $H, T =:= $t orelse T =:= $T;
 			P =:= $p orelse P =:= $P; S =:= $s orelse S =:= $S ->
 			P =:= $p orelse P =:= $P; S =:= $s orelse S =:= $S ->
-	parse_uri_skip_host(Rest, State, Method);
+	parse_uri_skip_host(Rest, State, Method, <<>>);
 parse_uri(<< $/, Rest/bits >>, State, Method) ->
 parse_uri(<< $/, Rest/bits >>, State, Method) ->
 	parse_uri_path(Rest, State, Method, << $/ >>);
 	parse_uri_path(Rest, State, Method, << $/ >>);
 parse_uri(_, State, _) ->
 parse_uri(_, State, _) ->
 	error_terminate(400, State, {connection_error, protocol_error,
 	error_terminate(400, State, {connection_error, protocol_error,
 		'Invalid request-line or request-target. (RFC7230 3.1.1, RFC7230 5.3)'}).
 		'Invalid request-line or request-target. (RFC7230 3.1.1, RFC7230 5.3)'}).
 
 
-parse_uri_skip_host(<< C, Rest/bits >>, State, Method) ->
+parse_uri_skip_host(<< C, Rest/bits >>, State, Method, SoFar) ->
 	case C of
 	case C of
-		$\r -> error_terminate(400, State, {connection_error, protocol_error,
-			'The request-target must not be followed by a line break. (RFC7230 3.1.1)'});
-		$@ -> error_terminate(400, State, {connection_error, protocol_error,
-			'Absolute URIs must not include a userinfo component. (RFC7230 2.7.1)'});
+		$\r ->
+			error_terminate(400, State, {connection_error, protocol_error,
+				'The request-target must not be followed by a line break. (RFC7230 3.1.1)'});
+		$@ ->
+			error_terminate(400, State, {connection_error, protocol_error,
+				'Absolute URIs must not include a userinfo component. (RFC7230 2.7.1)'});
+		C when SoFar =:= <<>> andalso
+				((C =:= $/) orelse (C =:= $\s) orelse (C =:= $?) orelse (C =:= $#)) ->
+			error_terminate(400, State, {connection_error, protocol_error,
+				'Absolute URIs must include an authority component. (RFC7230 2.7.1)'});
 		$/ -> parse_uri_path(Rest, State, Method, <<"/">>);
 		$/ -> parse_uri_path(Rest, State, Method, <<"/">>);
 		$\s -> parse_version(Rest, State, Method, <<"/">>, <<>>);
 		$\s -> parse_version(Rest, State, Method, <<"/">>, <<>>);
 		$? -> parse_uri_query(Rest, State, Method, <<"/">>, <<>>);
 		$? -> parse_uri_query(Rest, State, Method, <<"/">>, <<>>);
 		$# -> skip_uri_fragment(Rest, State, Method, <<"/">>, <<>>);
 		$# -> skip_uri_fragment(Rest, State, Method, <<"/">>, <<>>);
-		_ -> parse_uri_skip_host(Rest, State, Method)
+		C -> parse_uri_skip_host(Rest, State, Method, <<SoFar/binary, C>>)
 	end.
 	end.
 
 
 parse_uri_path(<< C, Rest/bits >>, State, Method, SoFar) ->
 parse_uri_path(<< C, Rest/bits >>, State, Method, SoFar) ->