24
1
mirror of https://github.com/processone/ejabberd.git synced 2024-07-04 23:15:31 +02:00

Don't ignore Length parameter in tls:recv

This commit is contained in:
Alexey Shchepin 2012-03-07 16:19:59 +02:00
parent 60d422eb8e
commit 0b423eb287
3 changed files with 50 additions and 48 deletions

View File

@ -32,7 +32,7 @@
-export([start/0, start_link/0,
tcp_to_tls/2, tls_to_tcp/1,
send/2,
recv/2, recv/3, recv_data/2,
recv/2, recv/3,
setopts/2,
sockname/1, peername/1,
controlling_process/2,
@ -160,29 +160,34 @@ tls_to_tcp(#tlssock{tcpsock = TCPSocket, tlsport = Port}) ->
recv(Socket, Length) ->
recv(Socket, Length, infinity).
recv(#tlssock{tcpsock = TCPSocket} = TLSSock,
_Length, Timeout) ->
%% The Length argument cannot be used for gen_tcp:recv/3, because the
%% compressed size does not equal the desired uncompressed one.
case gen_tcp:recv(TCPSocket, 0, Timeout) of
{ok, Packet} ->
recv_data(TLSSock, Packet);
{error, _Reason} = Error ->
Error
recv(#tlssock{tcpsock = TCPSocket, tlsport = Port} = TLSSock,
Length, Timeout) ->
case port_control(Port, ?GET_DECRYPTED_INPUT, <<Length:32>>) of
<<0>> ->
case gen_tcp:recv(TCPSocket, 0, Timeout) of
{ok, Packet} ->
recv_data(TLSSock, Packet, Length);
{error, _Reason} = Error ->
Error
end;
<<0, In/binary>> ->
{ok, In};
<<1, Error/binary>> ->
{error, binary_to_list(Error)}
end.
recv_data(TLSSock, Packet) ->
case catch recv_data1(TLSSock, Packet) of
recv_data(TLSSock, Packet, Length) ->
case catch recv_data1(TLSSock, Packet, Length) of
{'EXIT', Reason} ->
{error, Reason};
Res ->
Res
end.
recv_data1(#tlssock{tcpsock = TCPSocket, tlsport = Port}, Packet) ->
recv_data1(#tlssock{tcpsock = TCPSocket, tlsport = Port}, Packet, Length) ->
case port_control(Port, ?SET_ENCRYPTED_INPUT, Packet) of
<<0>> ->
case port_control(Port, ?GET_DECRYPTED_INPUT, []) of
case port_control(Port, ?GET_DECRYPTED_INPUT, <<Length:32>>) of
<<0, In/binary>> ->
case port_control(Port, ?GET_ENCRYPTED_OUTPUT, []) of
<<0, Out/binary>> ->

View File

@ -434,13 +434,22 @@ static ErlDrvSSizeT tls_drv_control(ErlDrvData handle,
"SSL_do_handshake failed");
}
if (SSL_is_init_finished(d->ssl)) {
size_t req_size = 0;
if (len == 4)
{
req_size =
(buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
}
size = BUF_SIZE + 1;
rlen = 1;
b = driver_alloc_binary(size);
b->orig_bytes[0] = 0;
while ((res = SSL_read(d->ssl,
b->orig_bytes + rlen, BUF_SIZE)) > 0)
while ((req_size == 0 || rlen < req_size + 1) &&
(res = SSL_read(d->ssl,
b->orig_bytes + rlen,
(req_size == 0 || req_size + 1 >= size) ?
size - rlen : req_size + 1 - rlen)) > 0)
{
//printf("%d bytes of decrypted data read from state machine\r\n",res);
rlen += res;

View File

@ -192,38 +192,30 @@ receive_headers(State) ->
_ ->
case Data of
{ok, Binary} ->
process_requests(State, binary_to_list(Binary));
{Request, Trail} = parse_request(
State,
State#state.trail ++ binary_to_list(Binary)),
State1 = State#state{trail = Trail},
NewState = lists:foldl(
fun(D, S) ->
case S#state.end_of_request of
true ->
S;
_ ->
process_header(S, D)
end
end, State1, Request),
case NewState#state.end_of_request of
true ->
ok;
_ ->
receive_headers(NewState)
end;
_ ->
ok
end
end.
process_requests(State, Data) ->
{Request, Trail} = parse_request(
State,
State#state.trail ++ Data),
State1 = State#state{trail = Trail},
NewState = lists:foldl(
fun(D, S) ->
case S#state.end_of_request of
true ->
S;
_ ->
process_header(S, D)
end
end, State1, Request),
case State1#state.trail of
[] ->
case NewState#state.end_of_request of
true ->
ok;
_ ->
receive_headers(NewState)
end;
_ ->
process_requests(State1, "")
end.
process_header(State, Data) ->
SockMod = State#state.sockmod,
Socket = State#state.socket,
@ -599,11 +591,7 @@ recv_data(_State, 0, Acc) ->
recv_data(State, Len, Acc) ->
case State#state.trail of
[] ->
Len2 = case State#state.sockmod of
gen_tcp -> Len;
_ -> 0
end,
case (State#state.sockmod):recv(State#state.socket, Len2, 300000) of
case (State#state.sockmod):recv(State#state.socket, Len, 300000) of
{ok, Data} ->
recv_data(State, Len - size(Data), [Acc | [Data]]);
_ ->