From 67a0e8d70f0caf8b85e0cf2031333236b2a3dcdf Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sun, 24 Jan 2016 14:46:19 +0200 Subject: Add checksum verification --- bpkg/fetch.cxx | 71 ++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 12 deletions(-) (limited to 'bpkg/fetch.cxx') diff --git a/bpkg/fetch.cxx b/bpkg/fetch.cxx index c47fb55..257d903 100644 --- a/bpkg/fetch.cxx +++ b/bpkg/fetch.cxx @@ -5,7 +5,7 @@ #include #include -#include // uint16_t +#include #include #include @@ -13,6 +13,7 @@ #include +#include #include #include @@ -354,7 +355,7 @@ namespace bpkg static path fetch_path; static kind fetch_kind; - kind + static kind check (const common_options& o) { if (!fetch_path.empty ()) @@ -523,6 +524,8 @@ namespace bpkg return r; } + // If sha256sum is empty, then don't verify. + // template static M fetch_manifest (const common_options& o, @@ -530,6 +533,7 @@ namespace bpkg const string& host, uint16_t port, const path& f, + const string& sha256sum, bool ignore_unknown) { string url (to_url (proto, host, port, f)); @@ -540,9 +544,32 @@ namespace bpkg ifdstream is (pr.in_ofd); is.exceptions (ifdstream::badbit | ifdstream::failbit); - manifest_parser mp (is, url); - M m (mp, ignore_unknown); - is.close (); + M m; + if (sha256sum.empty ()) + { + manifest_parser mp (is, url); + m = M (mp, ignore_unknown); + is.close (); + } + else + { + // Unfortunately we cannot rewind STDOUT as we do below for files. + // There doesn't seem to be anything better than reading the entire + // file into memory and then streaming it twice, once to calculate + // the checksum and the second time to actually parse. + // + stringstream ss; + ss << is.rdbuf (); + is.close (); + + if (sha256sum != sha256 (o, ss)) + throw checksum_mismatch (); + + ss.clear (); ss.seekg (0); // Rewind. + + manifest_parser mp (ss, url); + m = M (mp, ignore_unknown); + } if (pr.wait ()) return m; @@ -618,9 +645,14 @@ namespace bpkg return r; } + // If sha256sum is empty, then don't verify. + // template static M - fetch_manifest (const path& f, bool ignore_unknown) + fetch_manifest (const common_options* o, + const path& f, + const string& sha256sum, + bool ignore_unknown) { if (!exists (f)) fail << "file " << f << " does not exist"; @@ -631,6 +663,16 @@ namespace bpkg ifs.exceptions (ofstream::badbit | ofstream::failbit); ifs.open (f.string ()); + if (!sha256sum.empty ()) + { + assert (o != nullptr); + + if (sha256sum != sha256 (*o, ifs)) + throw checksum_mismatch (); + + ifs.seekg (0); // Rewind the file stream. + } + manifest_parser mp (ifs, f.string ()); return M (mp, ignore_unknown); } @@ -651,12 +693,17 @@ namespace bpkg repository_manifests fetch_repositories (const dir_path& d, bool iu) { - return fetch_manifest (d / repositories, iu); + return fetch_manifest ( + nullptr, + d / repositories, + "", // No checksum verification. + iu); } repository_manifests fetch_repositories (const common_options& o, const repository_location& rl, + const string& sha256sum, bool iu) { assert (rl.remote () || rl.absolute ()); @@ -665,8 +712,8 @@ namespace bpkg return rl.remote () ? fetch_manifest ( - o, rl.proto (), rl.host (), rl.port (), f, iu) - : fetch_manifest (f, iu); + o, rl.proto (), rl.host (), rl.port (), f, sha256sum, iu) + : fetch_manifest (&o, f, sha256sum, iu); } static const path packages ("packages"); @@ -674,7 +721,7 @@ namespace bpkg package_manifests fetch_packages (const dir_path& d, bool iu) { - return fetch_manifest (d / packages, iu); + return fetch_manifest (nullptr, d / packages, "", iu); } package_manifests @@ -688,8 +735,8 @@ namespace bpkg return rl.remote () ? fetch_manifest ( - o, rl.proto (), rl.host (), rl.port (), f, iu) - : fetch_manifest (f, iu); + o, rl.proto (), rl.host (), rl.port (), f, "", iu) + : fetch_manifest (&o, f, "", iu); } path -- cgit v1.1