Skip to content

Commit

Permalink
Unquote basic auth username and password (#5)
Browse files Browse the repository at this point in the history
Unquote username and password which were parsed by ibrowse_lib:parse_url/1 before inserting them in the basic auth header.

Previously if the user had characters like @ in their username or password, and they were percent-encoded, they were inserted encoded in the basic auth header which lead to authentication failure.
  • Loading branch information
jiahuili430 authored and nickva committed May 7, 2021
1 parent 9a6b57b commit e9f77d2
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 3 deletions.
4 changes: 3 additions & 1 deletion src/ibrowse_http_client.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1057,7 +1057,9 @@ add_auth_headers(#url{username = User,
[{"Authorization", ["Basic ", http_auth_basic(U, P)]} | Headers]
end;
_ ->
[{"Authorization", ["Basic ", http_auth_basic(User, UPw)]} | Headers]
User1 = ibrowse_lib:unquote(User),
UPw1 = ibrowse_lib:unquote(UPw),
[{"Authorization", ["Basic ", http_auth_basic(User1, UPw1)]} | Headers]
end,
add_proxy_auth_headers(State, Headers_1).

Expand Down
43 changes: 41 additions & 2 deletions src/ibrowse_lib.erl
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,14 @@
get_value/3,
parse_url/1,
printable_date/0,
printable_date/1
unquote/1
]).

-define(PERCENT, 37). % $\%
-define(IS_HEX(C), ((C >= $0 andalso C =< $9) orelse
(C >= $a andalso C =< $f) orelse
(C >= $A andalso C =< $F))).

get_trace_status(Host, Port) ->
ibrowse:get_config_value({trace, Host, Port}, false).

Expand Down Expand Up @@ -389,6 +394,29 @@ printable_date(Now) ->
$:,
integer_to_list(MicroSecs div 1000)].

%% @spec unquote(string() | binary()) -> string()
%% @doc Unquote a URL encoded string.
unquote(Binary) when is_binary(Binary) ->
unquote(binary_to_list(Binary));
unquote(String) ->
qs_revdecode(lists:reverse(String)).

qs_revdecode(S) ->
qs_revdecode(S, []).

qs_revdecode([], Acc) ->
Acc;
qs_revdecode([$+ | Rest], Acc) ->
qs_revdecode(Rest, [$\s | Acc]);
qs_revdecode([Lo, Hi, ?PERCENT | Rest], Acc) when ?IS_HEX(Lo), ?IS_HEX(Hi) ->
qs_revdecode(Rest, [(unhexdigit(Lo) bor (unhexdigit(Hi) bsl 4)) | Acc]);
qs_revdecode([C | Rest], Acc) ->
qs_revdecode(Rest, [C | Acc]).

unhexdigit(C) when C >= $0, C =< $9 -> C - $0;
unhexdigit(C) when C >= $a, C =< $f -> C - $a + 10;
unhexdigit(C) when C >= $A, C =< $F -> C - $A + 10.

do_trace(Fmt, Args) ->
do_trace(get(my_trace_flag), Fmt, Args).

Expand Down Expand Up @@ -462,4 +490,15 @@ parse_url_test() ->
?assertMatch(Expected_result, parse_url(Url))
end, Urls).

-endif.
unquote_test() ->
?assertEqual("foo bar",
unquote("foo+bar")),
?assertEqual("foo bar",
unquote("foo%20bar")),
?assertEqual("foo\r\n",
unquote("foo%0D%0A")),
?assertEqual("foo\r\n",
unquote(<<"foo%0D%0A">>)),
ok.

-endif.

0 comments on commit e9f77d2

Please sign in to comment.