Move handshake packet encoding/decoding from mtp_down_con to mtp_rpc

parent 1cf3a34b
...@@ -17,6 +17,9 @@ ...@@ -17,6 +17,9 @@
shutdown/1, shutdown/1,
send/2, send/2,
ack/3]). ack/3]).
-ifdef(TEST).
-export([get_middle_key/1]).
-endif.
%% gen_server callbacks %% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
...@@ -388,20 +391,12 @@ tcp_connect(Host, Port) -> ...@@ -388,20 +391,12 @@ tcp_connect(Host, Port) ->
Err Err
end. end.
-define(RPC_NONCE, <<170,135,203,122>>).
-define(RPC_HANDSHAKE, <<245,238,130,118>>).
-define(RPC_FLAGS, <<0, 0, 0, 0>>).
down_handshake1(S) -> down_handshake1(S) ->
RpcNonce = ?RPC_NONCE,
<<KeySelector:4/binary, _/binary>> = Key = mtp_config:get_secret(), <<KeySelector:4/binary, _/binary>> = Key = mtp_config:get_secret(),
CryptoTs = os:system_time(seconds), CryptoTs = os:system_time(seconds),
Nonce = crypto:strong_rand_bytes(16), Nonce = crypto:strong_rand_bytes(16),
Msg = <<RpcNonce/binary, Schema = 1, %AES
KeySelector/binary, Msg = mtp_rpc:encode_nonce({nonce, KeySelector, Schema, CryptoTs, Nonce}),
1:32/little, %AES
CryptoTs:32/little,
Nonce/binary>>,
S1 = S#state{stage = handshake_1, S1 = S#state{stage = handshake_1,
%% Use fake encryption codec %% Use fake encryption codec
codec = mtp_codec:new(mtp_noop_codec, mtp_noop_codec:new(), codec = mtp_codec:new(mtp_noop_codec, mtp_noop_codec:new(),
...@@ -409,11 +404,10 @@ down_handshake1(S) -> ...@@ -409,11 +404,10 @@ down_handshake1(S) ->
stage_state = {KeySelector, Nonce, CryptoTs, Key}}, stage_state = {KeySelector, Nonce, CryptoTs, Key}},
down_send(Msg, S1). down_send(Msg, S1).
down_handshake2(<<Type:4/binary, KeySelector:4/binary, Schema:32/little, _CryptoTs:4/binary, down_handshake2(Pkt, #state{stage_state = {MyKeySelector, CliNonce, MyTs, Key},
SrvNonce:16/binary>>, #state{stage_state = {MyKeySelector, CliNonce, MyTs, Key}, codec = Codec1,
codec = Codec1, sock = Sock} = S) ->
sock = Sock} = S) -> {nonce, KeySelector, Schema, _CryptoTs, SrvNonce} = mtp_rpc:decode_nonce(Pkt),
(Type == ?RPC_NONCE) orelse error({wrong_rpc_type, Type}),
(Schema == 1) orelse error({wrong_schema, Schema}), (Schema == 1) orelse error({wrong_schema, Schema}),
(KeySelector == MyKeySelector) orelse error({wrong_key_selector, KeySelector}), (KeySelector == MyKeySelector) orelse error({wrong_key_selector, KeySelector}),
{ok, {DownIp, DownPort}} = inet:peername(Sock), {ok, {DownIp, DownPort}} = inet:peername(Sock),
...@@ -430,10 +424,7 @@ down_handshake2(<<Type:4/binary, KeySelector:4/binary, Schema:32/little, _Crypto ...@@ -430,10 +424,7 @@ down_handshake2(<<Type:4/binary, KeySelector:4/binary, Schema:32/little, _Crypto
Codec = mtp_codec:new(mtp_aes_cbc, CryptoState, Codec = mtp_codec:new(mtp_aes_cbc, CryptoState,
PacketMod, PacketState), PacketMod, PacketState),
SenderPID = PeerPID = <<"IPIPPRPDTIME">>, SenderPID = PeerPID = <<"IPIPPRPDTIME">>,
Handshake = [?RPC_HANDSHAKE, Handshake = mtp_rpc:encode_handshake({handshake, SenderPID, PeerPID}),
?RPC_FLAGS,
SenderPID,
PeerPID],
down_send(Handshake, down_send(Handshake,
S#state{codec = Codec, S#state{codec = Codec,
stage = handshake_2, stage = handshake_2,
...@@ -465,10 +456,9 @@ get_middle_key(#{srv_n := Nonce, clt_n := MyNonce, clt_ts := MyTs, srv_ip := Srv ...@@ -465,10 +456,9 @@ get_middle_key(#{srv_n := Nonce, clt_n := MyNonce, clt_ts := MyTs, srv_ip := Srv
{Key, IV}. {Key, IV}.
down_handshake3(<<Type:4/binary, _Flags:4/binary, _SenderPid:12/binary, PeerPid:12/binary>>, down_handshake3(Pkt, #state{stage_state = PrevSenderPid, pool = Pool,
#state{stage_state = PrevSenderPid, pool = Pool, netloc = {Addr, Port}} = S) ->
netloc = {Addr, Port}} = S) -> {handshake, _SenderPid, PeerPid} = mtp_rpc:decode_handshake(Pkt),
(Type == ?RPC_HANDSHAKE) orelse error({wrong_rpc_type, Type}),
(PeerPid == PrevSenderPid) orelse error({wrong_sender_pid, PeerPid}), (PeerPid == PrevSenderPid) orelse error({wrong_sender_pid, PeerPid}),
ok = mtp_dc_pool:ack_connected(Pool, self()), ok = mtp_dc_pool:ack_connected(Pool, self()),
lager:info("~s:~w: handshake complete", [inet:ntoa(Addr), Port]), lager:info("~s:~w: handshake complete", [inet:ntoa(Addr), Port]),
......
...@@ -8,7 +8,15 @@ ...@@ -8,7 +8,15 @@
-module(mtp_rpc). -module(mtp_rpc).
-export([decode_packet/1, -export([decode_packet/1,
decode_nonce/1,
decode_handshake/1,
encode_nonce/1,
encode_handshake/1,
encode_packet/2]). encode_packet/2]).
%% For tests
-export([srv_decode_packet/1,
srv_encode_packet/1]).
%% Helpers
-export([inet_pton/1, -export([inet_pton/1,
encode_ip_port/2]). encode_ip_port/2]).
-export_type([codec/0]). -export_type([codec/0]).
...@@ -29,6 +37,11 @@ ...@@ -29,6 +37,11 @@
-define(RPC_SIMPLE_ACK, 155,64,172,59). %0x3bac409b -define(RPC_SIMPLE_ACK, 155,64,172,59). %0x3bac409b
-define(TL_PROXY_TAG, 174,38,30,219). -define(TL_PROXY_TAG, 174,38,30,219).
-define(RPC_NONCE, 170,135,203,122).
-define(RPC_HANDSHAKE, 245,238,130,118).
-define(RPC_FLAGS, 0, 0, 0, 0).
-define(FLAG_NOT_ENCRYPTED , 16#2). -define(FLAG_NOT_ENCRYPTED , 16#2).
-define(FLAG_HAS_AD_TAG , 16#8). -define(FLAG_HAS_AD_TAG , 16#8).
-define(FLAG_MAGIC , 16#1000). -define(FLAG_MAGIC , 16#1000).
...@@ -45,15 +58,31 @@ ...@@ -45,15 +58,31 @@
| {close_ext, conn_id()} | {close_ext, conn_id()}
| {simple_ack, conn_id(), binary()}. | {simple_ack, conn_id(), binary()}.
%% new(ClientIp, ClientPort, ProxyIp, ProxyPort, ProxyTag) -> decode_nonce(<<?RPC_NONCE,
%% new(ClientIp, ClientPort, ProxyIp, ProxyPort, ProxyTag, KeySelector:4/binary,
%% erlang:unique_integer()). Schema:32/little,
CryptoTs:32/little,
%% new(ClientIp, ClientPort, ProxyIp, ProxyPort, ProxyTag, ConnId) -> CliNonce:16/binary>>) ->
%% #rpc_st{client_addr = iolist_to_binary(encode_ip_port(ClientIp, ClientPort)), {nonce, KeySelector, Schema, CryptoTs, CliNonce}.
%% proxy_addr = iolist_to_binary(encode_ip_port(ProxyIp, ProxyPort)),
%% proxy_tag = ProxyTag, decode_handshake(<<?RPC_HANDSHAKE,
%% conn_id = ConnId}. ?RPC_FLAGS,
SenderPID:12/binary,
PeerPID:12/binary>>) ->
{handshake, SenderPID, PeerPID}.
encode_nonce({nonce, KeySelector, Schema, CryptoTs, SrvNonce}) ->
<<?RPC_NONCE,
KeySelector:4/binary,
Schema:32/little,
CryptoTs:32/little,
SrvNonce:16/binary>>.
encode_handshake({handshake, SenderPID, PeerPID}) ->
<<?RPC_HANDSHAKE,
0, 0, 0, 0, %Some flags
SenderPID:12/binary,
PeerPID:12/binary>>.
%% It expects that packet segmentation was done on previous layer %% It expects that packet segmentation was done on previous layer
%% See mtproto/mtproto-proxy.c:process_client_packet %% See mtproto/mtproto-proxy.c:process_client_packet
...@@ -99,6 +128,29 @@ encode_packet({data, Msg}, {{ConnId, ClientAddr, ProxyTag}, ProxyAddr}) -> ...@@ -99,6 +128,29 @@ encode_packet({data, Msg}, {{ConnId, ClientAddr, ProxyTag}, ProxyAddr}) ->
encode_packet(remote_closed, ConnId) -> encode_packet(remote_closed, ConnId) ->
<<?RPC_CLOSE_CONN, ConnId:64/little-signed>>. <<?RPC_CLOSE_CONN, ConnId:64/little-signed>>.
%%
%% Middle-proxy side encoding and decodong (FOR TESTS ONLY!)
%%
%% opposite of encode_packet
srv_decode_packet(<<?RPC_PROXY_REQ, _Flags:32/little, ConnId:64/little-signed,
_ClientAddrBin:20/binary, _ProxyAddrBin:20/binary,
24:32/little, ?TL_PROXY_TAG, 16, _ProxyTag:16/binary, 0, 0, 0,
Data/binary>>) ->
{data, ConnId, Data};
srv_decode_packet(<<?RPC_CLOSE_CONN, ConId:64/little-signed>>) ->
{remote_closed, ConId}.
%% Opposite of decode_packet
srv_encode_packet({proxy_ans, ConnId, Data}) ->
<<?RPC_PROXY_ANS,
0, 0, 0, 0, %some flags
ConnId:64/signed-little,
Data/binary>>;
srv_encode_packet({close_ext, ConnId}) ->
<<?RPC_CLOSE_EXT, ConnId:64/little-signed>>.
%% IP and port as 10 + 2 + 4 + 4 = 20b
-spec encode_ip_port(inet:ip_address(), inet:port_number()) -> iodata(). -spec encode_ip_port(inet:ip_address(), inet:port_number()) -> iodata().
encode_ip_port(IPv4, Port) when tuple_size(IPv4) == 4 -> encode_ip_port(IPv4, Port) when tuple_size(IPv4) == 4 ->
IpBin = inet_pton(IPv4), IpBin = inet_pton(IPv4),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment