Skip to content

Commit c40e807

Browse files
committed
Merge v0.13.14
2 parents 59bd2a7 + 6ce1a0b commit c40e807

File tree

6 files changed

+237
-3
lines changed

6 files changed

+237
-3
lines changed

apps/tpic2/src/tpic2_tls.erl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,11 @@ loop(State=#{parent:=Parent, socket:=Socket, transport:=Transport, opts:=_Opts,
164164
?LOG_ERROR("Received stray message ~p.~n", [Msg]),
165165
?MODULE:loop(State)
166166
after 10000 -> %to avoid killing on code change
167-
ok=send_msg(#{null=><<"KA">>},State),
168-
?MODULE:loop(State)
167+
case send_msg(#{null=><<"KA">>},State) of
168+
ok -> ?MODULE:loop(State);
169+
{error, closed} ->
170+
exit(normal)
171+
end
169172
end.
170173

171174
system_continue(_PID,_,{State}) ->

apps/tpnode/src/tpnode.app.src

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
tinymq,
1010
jsx,
1111
cowboy,
12+
certifi,
1213
rocksdb,
1314
gb_merkle_trees,
1415
msgpack,

apps/tpnode/src/tpnode_hotfix.erl

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
-module(tpnode_hotfix).
2+
-export([install/1, autoload/0, unpack/1, load/1, load1/2, validkey/1]).
3+
4+
-define(STD_KEYS,[
5+
"302A300506032B65700321002B3A6C9A401865F65004665336A9CA3E33D029D7AE2B5204EBFBC0A4910CFA1E",
6+
"032FB1B9DF699380904A803E579AB7392B7DF26881DA07D1ABC9DB198919B03782"
7+
]).
8+
9+
validkey(PubKey) ->
10+
ValidKeys=lists:foldl(
11+
fun(HexKey,A) ->
12+
maps:put(tpecdsa:cmp_pubkey(hex:decode(HexKey)),1,A)
13+
end, #{},
14+
application:get_env(tpnode, hotfix_keys, ?STD_KEYS)
15+
),
16+
PK=tpecdsa:cmp_pubkey(PubKey),
17+
maps:is_key(PK,ValidKeys).
18+
19+
20+
versig({true,#{extra := SigXD}}=Any) ->
21+
case proplists:get_value(pubkey,SigXD) of
22+
undefined ->
23+
logger:notice("Versig failed to find pubkey: ~p",[Any]),
24+
false;
25+
PubKey ->
26+
validkey(PubKey)
27+
end;
28+
29+
versig(Any) ->
30+
logger:notice("Versig failed: ~p",[Any]),
31+
false.
32+
33+
autoload() ->
34+
ok.
35+
36+
install(Fix) ->
37+
Host=application:get_env(tpnode,hotfix_host,"https://hotfix.thepower.io"),
38+
39+
case get(Host, "/thepower/hotfix/tpnode/"++Fix) of
40+
{200, Bin} ->
41+
{ok, Files, Sig} = unpack(Bin),
42+
case versig(Sig) of
43+
true ->
44+
code:delete(hotfix_compatible),
45+
code:purge(hotfix_compatible),
46+
code:delete(hotfix_compatible),
47+
case proplists:get_value("hotfix_compatible.beam",Files) of
48+
undefined -> {error, that_is_not_hotfix};
49+
Beam ->
50+
load1("hotfix_compatible.beam",Beam),
51+
{file,_} = code:is_loaded(hotfix_compatible),
52+
ok = hotfix_compatible:check(Files),
53+
{ok,load(Files)}
54+
end;
55+
false ->
56+
{error,badsig}
57+
end;
58+
{Code,_} ->
59+
{error,{http,Code}}
60+
end.
61+
62+
63+
load1(Filename, Bin) ->
64+
N=filename:basename(Filename),
65+
case string:split(N,".") of
66+
[Module,"beam"] ->
67+
ModName=list_to_atom(Module),
68+
{Filename,case code:load_binary(ModName,Filename,Bin) of
69+
{error, R} ->
70+
R;
71+
{module, _} ->
72+
ok
73+
end};
74+
_ ->
75+
false
76+
end.
77+
78+
load([]) -> [];
79+
80+
load([{"hotfix_compatible.beam",_}|Files]) ->
81+
load(Files);
82+
83+
load([{Filename,<<"FOR1",_/binary>> = Bin}|Files]) ->
84+
case load1(Filename,Bin) of
85+
false ->
86+
load(Files);
87+
{_,_} = E ->
88+
[E|load(Files)]
89+
end;
90+
91+
load([_|Files]) ->
92+
load(Files).
93+
94+
split_bin(<<HL:16/big,0,Signatures:(HL-1)/binary,ZIP/binary>>) ->
95+
{Signatures,ZIP}.
96+
97+
unpack(Bin) ->
98+
{Sig,Zip}=split_bin(Bin),
99+
{ok,Files}=zip:extract(Zip,[memory]),
100+
Hash=crypto:hash(sha256,Zip),
101+
CheckSig=bsig:checksig1(Hash,Sig),
102+
{ok, Files, CheckSig}.
103+
104+
get(Node, Path) ->
105+
application:ensure_all_started(gun),
106+
{ok, ConnPid} = connect(Node),
107+
StreamRef = gun:get(ConnPid, Path, []),
108+
{response, Fin, Code, _Headers} = gun:await(ConnPid, StreamRef),
109+
case Code of
110+
200 ->
111+
Body=case Fin of
112+
fin -> <<>>;
113+
nofin ->
114+
{ok, Body2} = gun:await_body(ConnPid, StreamRef),
115+
Body2
116+
end,
117+
gun:close(ConnPid),
118+
{Code,Body};
119+
Code ->
120+
gun:close(ConnPid),
121+
logger:error("Can't fetch ~s: code ~w",[Path,Code]),
122+
{Code,<<>>}
123+
end.
124+
125+
connect(Node) ->
126+
{Host, Port, Opts,_} = parse_url(Node),
127+
{ok, ConnPid} = gun:open(Host,Port,Opts),
128+
case gun:await_up(ConnPid) of
129+
{ok, _} ->
130+
{ok, ConnPid};
131+
{error,Other} ->
132+
throw(Other)
133+
end.
134+
135+
parse_url(Node) when is_binary(Node) ->
136+
parse_url(binary_to_list(Node));
137+
138+
parse_url(Node) when is_list(Node) ->
139+
CaCerts = certifi:cacerts(),
140+
CHC=[
141+
{match_fun, public_key:pkix_verify_hostname_match_fun(https)}
142+
],
143+
#{scheme:=Sch,
144+
path:=Path,
145+
host:=Host}=P = uri_string:parse(Node),
146+
{Opts,Port}=case Sch of
147+
"httpsi" ->
148+
case get(warned) of
149+
undefined ->
150+
logger:notice("-=-=-= [ connection is insecure ] =-=-=-~n",[]),
151+
put(warned, true);
152+
_ ->
153+
ok
154+
end,
155+
{
156+
#{ transport=>tls,
157+
transport_opts => [
158+
{versions,['tlsv1.2']},
159+
{verify,verify_none}
160+
]
161+
},
162+
maps:get(port,P,443)
163+
};
164+
"https" -> {
165+
#{ transport=>tls,
166+
transport_opts => [{verify, verify_peer},
167+
{customize_hostname_check, CHC},
168+
{depth, 5},
169+
{versions,['tlsv1.2']},
170+
%{versions,['tlsv1.3']},
171+
{cacerts, CaCerts}
172+
]
173+
},
174+
maps:get(port,P,443)
175+
};
176+
"http" ->
177+
case get(warned) of
178+
undefined ->
179+
logger:notice("-=-=-= [ connection is not encrypted, so insecure ] =-=-=-~n",[]),
180+
put(warned, true);
181+
_ ->
182+
ok
183+
end,
184+
{
185+
#{ transport=>tcp },
186+
maps:get(port,P,80)
187+
}
188+
end,
189+
{Host,
190+
Port,
191+
Opts,
192+
#{path=>Path}
193+
}.
194+
195+

apps/tpnode/src/tpnode_httpapi.erl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,36 @@ h(<<"POST">>, [<<"node">>, <<"new_peer">>], Req) ->
243243
answer(#{ result=> false, error=><<"bad_input">>})
244244
end;
245245

246+
h(<<"POST">>, [<<"node">>, <<"hotfix">>], Req) ->
247+
{RemoteIP, _Port}=cowboy_req:peer(Req),
248+
?LOG_DEBUG("New hotfix request from ~s", [inet:ntoa(RemoteIP)]),
249+
case apixiom:bodyjs(Req) of
250+
#{<<"fixid">>:=ID, <<"t">>:=Timestamp, <<"sig">>:=Sig} ->
251+
T=os:system_time(millisecond),
252+
SigBinH=crypto:hash(sha256,<<"httphfix",Timestamp:64/big, ID/binary>>),
253+
Valid=bsig:checksig1(SigBinH,
254+
base64:decode(Sig),
255+
fun(PubKey,_) ->
256+
tpnode_hotfix:validkey(PubKey)
257+
end
258+
),
259+
260+
if(abs(T-Timestamp) > 60000) ->
261+
answer(#{ result=> false, error=><<"bad_timestamp">>, t=>T});
262+
Valid =/= false ->
263+
Files=tpnode_hotfix:install(ID),
264+
logger:debug("hotfix Files ~p",[Files]),
265+
answer(#{ result => ok, r=>list_to_binary(
266+
io_lib:format("~p",[Files])
267+
)});
268+
true ->
269+
answer(#{ result=> false, error=><<"bad_signature">>, t=>T})
270+
end;
271+
Body ->
272+
?LOG_INFO("hotfix Bad req ~p~n",[Body]),
273+
answer(#{ result=> false, error=><<"bad_input">>})
274+
end;
275+
246276
h(<<"GET">>, [<<"contract">>, TAddr], _Req) ->
247277
try
248278
Addr=case TAddr of

rebar.config

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
{mkmap, {git, "https://github.com/cleverfox/mkmap.git", {branch, "master"}}},
4545
{tables, {git, "https://github.com/cleverfox/tables", {branch, "master"}}},
4646
{wanode, {git, "https://github.com/thepower/wanode.git", {branch, "master"}}},
47+
{certifi, {git, "https://github.com/certifi/erlang-certifi.git", {branch, "master"}}},
4748

4849
{meck, {git, "https://github.com/eproxus/meck.git", {branch, "master"}}},
4950
{tpapi, {git, "https://github.com/thepower/tpapi", {branch, "master"}}},
@@ -69,7 +70,7 @@
6970

7071

7172
{relx, [
72-
{release, { thepower, "0.13.11" }, [tpnode,
73+
{release, { thepower, "0.13.14" }, [tpnode,
7374
sasl,
7475
runtime_tools
7576
]},

rebar.lock

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
{git,"https://github.com/benoitc/cbt.git",
44
{ref,"3b3754c593ded5cac845cca9b9db7f34f05e881d"}},
55
1},
6+
{<<"certifi">>,
7+
{git,"https://github.com/certifi/erlang-certifi.git",
8+
{ref,"da653d2b14e9daf0dde493acbf622b0d3cedc8c3"}},
9+
0},
610
{<<"cowboy">>,{pkg,<<"cowboy">>,<<"2.9.0">>},0},
711
{<<"cowdb">>,
812
{git,"https://github.com/refuge/cowdb.git",

0 commit comments

Comments
 (0)