You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by wi...@apache.org on 2020/01/13 19:31:32 UTC
[couchdb-mochiweb] 03/08: refactor websocket init code a little.
some style fixes
This is an automated email from the ASF dual-hosted git repository.
willholley pushed a commit to tag active-passive
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git
commit 101bfc57cb80bfb0f265b322290987df38e3b4c8
Author: Richard Jones <rj...@metabrew.com>
AuthorDate: Sat Oct 9 00:09:45 2010 +0100
refactor websocket init code a little. some style fixes
---
src/mochiweb_http.erl | 100 +++++++++++++++++++++++++-------------------------
1 file changed, 51 insertions(+), 49 deletions(-)
diff --git a/src/mochiweb_http.erl b/src/mochiweb_http.erl
index 8713235..d38c6d5 100644
--- a/src/mochiweb_http.erl
+++ b/src/mochiweb_http.erl
@@ -220,77 +220,79 @@ range_skip_length(Spec, Size) ->
invalid_range
end.
+%% Respond to the websocket upgrade request with valid signature
+%% or exit() if any of the sec- headers look suspicious.
websocket_init(Socket, Path, Headers) ->
Host = mochiweb_headers:get_value("Host", Headers),
%Origin = mochiweb_headers:get_value("origin", Headers), % TODO
SubProto = mochiweb_headers:get_value("Sec-Websocket-Protocol", Headers),
Key1 = mochiweb_headers:get_value("Sec-Websocket-Key1", Headers),
Key2 = mochiweb_headers:get_value("Sec-Websocket-Key2", Headers),
- % read the 8 random bytes sent after the client headers for websockets:
+ %% read the 8 random bytes sent after the client headers for websockets:
{ok, Key3} = mochiweb_socket:recv(Socket, 8, ?HEADERS_RECV_TIMEOUT),
- %io:format("Key1,2,3: ~p ~p ~p~n", [Key1, Key2, Key3]),
{N1,S1} = parse_seckey(Key1),
{N2,S2} = parse_seckey(Key2),
- %io:format("{N1,S1} {N2,S2}: ~p ~p~n",[ {N1,S1}, {N2,S2} ] ),
+ ok = websocket_verify_parsed_sec({N1,S1}, {N2,S2}),
+ Part1 = erlang:round(N1/S1),
+ Part2 = erlang:round(N2/S2),
+ Sig = crypto:md5( <<Part1:32/unsigned-integer, Part2:32/unsigned-integer,
+ Key3/binary>> ),
+ Proto = case mochiweb_socket:type(Socket) of
+ ssl -> "wss://";
+ plain -> "ws://"
+ end,
+ SubProtoHeader = case SubProto of
+ undefined -> "";
+ P -> ["Sec-WebSocket-Protocol: ", P, "\r\n"]
+ end,
+ Data = ["HTTP/1.1 101 Web Socket Protocol Handshake\r\n",
+ "Upgrade: WebSocket\r\n",
+ "Connection: Upgrade\r\n",
+ "Sec-WebSocket-Location: ", Proto,Host,Path, "\r\n",
+ "Sec-WebSocket-Origin: http://", Host, "\r\n",
+ SubProtoHeader,
+ "\r\n",
+ <<Sig/binary>>
+ ],
+ mochiweb_socket:send(Socket, Data),
+ ok.
+
+%% websocket seckey parser:
+%% extract integer by only looking at [0-9]+ in the string
+%% count spaces in the string
+%% returns: {int, numspaces}
+parse_seckey(Str) ->
+ parse_seckey1(Str, {"",0}).
+
+parse_seckey1("", {NumStr,NumSpaces}) ->
+ {list_to_integer(lists:reverse(NumStr)), NumSpaces};
+parse_seckey1([32|T], {Ret,NumSpaces}) -> % ASCII/dec space
+ parse_seckey1(T, {Ret, 1+NumSpaces});
+parse_seckey1([N|T], {Ret,NumSpaces}) when N >= 48, N =< 57 -> % ASCII/dec 0-9
+ parse_seckey1(T, {[N|Ret], NumSpaces});
+parse_seckey1([_|T], Acc) ->
+ parse_seckey1(T, Acc).
+
+%% exit if anything suspicious is detected
+websocket_verify_parsed_sec({N1,S1}, {N2,S2}) ->
case N1 > 4294967295 orelse
N2 > 4294967295 orelse
S1 == 0 orelse
S2 == 0 of
true ->
- % This is a symptom of an attack.
+ %% This is a symptom of an attack.
exit(websocket_attack);
false ->
case N1 rem S1 /= 0 orelse
N2 rem S2 /= 0 of
true ->
- % This can only happen if the client is not a conforming
- % WebSocket client.
- exit(dodgy_client);
+ %% This can only happen if the client is not a conforming
+ %% WebSocket client.
+ exit(websocket_client_misspoke);
false ->
- Part1 = erlang:round(N1/S1),
- Part2 = erlang:round(N2/S2),
- %io:format("Part1 : ~p Part2: ~p~n", [Part1, Part2]),
- Sig = crypto:md5( <<Part1:32/unsigned-integer,
- Part2:32/unsigned-integer,
- Key3/binary>> ),
- Proto = case mochiweb_socket:type(Socket) of
- ssl -> "wss://";
- plain -> "ws://"
- end,
- SubProtoHeader = case SubProto of
- undefined -> "";
- P -> ["Sec-WebSocket-Protocol: ",
- P, "\r\n"]
- end,
- Data = ["HTTP/1.1 101 Web Socket Protocol Handshake\r\n",
- "Upgrade: WebSocket\r\n",
- "Connection: Upgrade\r\n",
- "Sec-WebSocket-Location: ", Proto,Host,Path, "\r\n",
- "Sec-WebSocket-Origin: http://", Host, "\r\n",
- SubProtoHeader,
- "\r\n",
- <<Sig/binary>>
- ],
- mochiweb_socket:send(Socket, Data),
- ok
+ ok
end
end.
-
-% websocket seckey parser:
-% extract integer by only looking at [0-9]+ in the string
-% count spaces in the string
-% returns: {int, numspaces}
-parse_seckey(Str) ->
- parse_seckey1(Str, {"",0}).
-
-parse_seckey1("", {NumStr,NumSpaces}) ->
- {list_to_integer(lists:reverse(NumStr)), NumSpaces};
-parse_seckey1([32|T], {Ret,NumSpaces}) -> % ASCII/dec space
- parse_seckey1(T, {Ret, 1+NumSpaces});
-parse_seckey1([N|T], {Ret,NumSpaces}) when N >= 48, N =< 57 -> % ASCII/dec 0-9
- parse_seckey1(T, {[N|Ret], NumSpaces});
-parse_seckey1([_|T], Acc) ->
- parse_seckey1(T, Acc).
%%
%% Tests