summaryrefslogtreecommitdiff
path: root/src/rebar_fetch.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/rebar_fetch.erl')
-rw-r--r--src/rebar_fetch.erl48
1 files changed, 37 insertions, 11 deletions
diff --git a/src/rebar_fetch.erl b/src/rebar_fetch.erl
index ec16089..16840eb 100644
--- a/src/rebar_fetch.erl
+++ b/src/rebar_fetch.erl
@@ -40,16 +40,7 @@ download_source(AppDir, Source, State) ->
ok = rebar_file_utils:mv(TmpDir, filename:absname(AppDir1)),
true;
{tarball, File} ->
- ec_file:mkdir_p(AppDir1),
- {ok, Files} = erl_tar:extract(File, [memory]),
-
- code:del_path(filename:absname(filename:join(AppDir1, "ebin"))),
- ec_file:remove(filename:absname(AppDir1), [recursive]),
-
- {"contents.tar.gz", Binary} = lists:keyfind("contents.tar.gz", 1, Files),
- ok = erl_tar:extract({binary, Binary},
- [{cwd, filename:absname(AppDir1)}, compressed]),
- true
+ verify_and_extract(File, Source, AppDir1, State)
end
catch
C:T ->
@@ -69,7 +60,11 @@ needs_update(AppDir, Source, State) ->
end.
format_error({fetch_fail, Source}) ->
- io_lib:format("Failed to fetch and copy dep: ~p", [Source]).
+ io_lib:format("Failed to fetch and copy dep: ~p", [Source]);
+format_error({bad_checksum, File}) ->
+ io_lib:format("Checksum mismatch against tarball in ~s", [File]);
+format_error({bad_registry_checksum, File}) ->
+ io_lib:format("Checksum mismatch against registry in ~s", [File]).
get_resource_type({Type, Location}, Resources) ->
find_resource_module(Type, Location, Resources);
@@ -93,3 +88,34 @@ find_resource_module(Type, Location, Resources) ->
{Type, Module} ->
Module
end.
+
+verify_and_extract(File, Source, AppDir, State) ->
+ ec_file:mkdir_p(AppDir),
+ {ok, Files} = erl_tar:extract(File, [memory]),
+
+ code:del_path(filename:absname(filename:join(AppDir, "ebin"))),
+ ec_file:remove(filename:absname(AppDir), [recursive]),
+
+ {"contents.tar.gz", Contents} = lists:keyfind("contents.tar.gz", 1, Files),
+ {"VERSION", Version} = lists:keyfind("VERSION", 1, Files),
+ {"metadata.config", Meta} = lists:keyfind("metadata.config", 1, Files),
+
+ Checksum = checksum(Contents, Version, Meta),
+ RegistryChecksum = rebar_packages:registry_checksum(Source, State),
+ {"CHECKSUM", TarChecksum} = lists:keyfind("CHECKSUM", 1, Files),
+
+ if
+ Checksum =/= TarChecksum ->
+ ?PRV_ERROR({bad_checksum, File});
+ Checksum =/= RegistryChecksum ->
+ ?PRV_ERROR({bad_registry_checksum, File});
+ true ->
+ ok = erl_tar:extract({binary, Contents},
+ [{cwd, filename:absname(AppDir)}, compressed]),
+ true
+ end.
+
+checksum(Contents, Version, Meta) ->
+ Blob = <<Version/binary, Meta/binary, Contents/binary>>,
+ <<X:256/big-unsigned-integer>> = crypto:hash(sha256, Blob),
+ list_to_binary(string:to_upper(lists:flatten(io_lib:format("~64.16.0b", [X])))).