diff options
-rw-r--r-- | libbpkg/manifest.cxx | 57 | ||||
-rw-r--r-- | libbpkg/manifest.hxx | 6 | ||||
-rw-r--r-- | tests/manifest/testscript | 3 |
3 files changed, 62 insertions, 4 deletions
diff --git a/libbpkg/manifest.cxx b/libbpkg/manifest.cxx index 78e3f2e..d14437b 100644 --- a/libbpkg/manifest.cxx +++ b/libbpkg/manifest.cxx @@ -17,7 +17,7 @@ #include <libbutl/path.mxx> #include <libbutl/base64.mxx> #include <libbutl/utility.mxx> // casecmp(), lcase(), alpha(), - // digit() + // digit(), xdigit() #include <libbutl/manifest-parser.mxx> #include <libbutl/manifest-serializer.mxx> @@ -55,7 +55,7 @@ namespace bpkg if (s.size () != 64) return false; - for (const auto& c: s) + for (const char& c: s) { if ((c < 'a' || c > 'f' ) && !digit (c)) return false; @@ -64,6 +64,28 @@ namespace bpkg return true; } + inline static bool + valid_fingerprint (const string& s) noexcept + { + size_t n (s.size ()); + if (n != 32 * 3 - 1) + return false; + + for (size_t i (0); i != n; ++i) + { + char c (s[i]); + if ((i + 1) % 3 == 0) // Must be the colon, + { + if (c != ':') + return false; + } + else if (!xdigit (c)) // Must be a hex digit. + return false; + } + + return true; + } + template <typename T> static string concatenate (const T& s, const char* delim = ", ") @@ -2610,6 +2632,16 @@ namespace bpkg r.certificate = move (v); } + else if (n == "trust") + { + if (r.trust) + bad_name ("trust redefinition"); + + if (!valid_fingerprint (v)) + bad_value ("invalid fingerprint"); + + r.trust = move (v); + } else if (n == "fragment") { if (r.fragment) @@ -2662,15 +2694,22 @@ namespace bpkg bad_value (e.what ()); } - // Verify that all non-optional values were specified. + // Verify that all non-optional values were specified and the optional ones + // are allowed. // // - location can be omitted // - role can be omitted + // - trust, url, email, summary, description and certificate are allowed // if (r.role && r.location.empty () != (*r.role == repository_role::base)) bad_value ("invalid role"); - if (r.effective_role () != repository_role::base) + bool base (r.effective_role () == repository_role::base); + + if (r.trust && (base || r.location.type () != repository_type::pkg)) + bad_value ("trust not allowed"); + + if (!base) { if (r.url) bad_value ("url not allowed"); @@ -2773,6 +2812,16 @@ namespace bpkg s.next ("certificate", *certificate); } + if (trust) + { + assert (b || !location.empty ()); + + if (b || location.type () != repository_type::pkg) + bad_value ("trust not allowed"); + + s.next ("trust", *trust); + } + if (fragment) s.next ("fragment", *fragment); diff --git a/libbpkg/manifest.hxx b/libbpkg/manifest.hxx index 68c4bc7..15d19fc 100644 --- a/libbpkg/manifest.hxx +++ b/libbpkg/manifest.hxx @@ -905,6 +905,12 @@ namespace bpkg butl::optional<std::string> description; butl::optional<std::string> certificate; + // The repository fingerprint to trust. May only be present for the + // prerequisite or complement repository and only for repository types + // that support authentication (currently only pkg). + // + butl::optional<std::string> trust; + // The repository fragment id this repository belongs to (may only be // present for multi-fragment repositories). // diff --git a/tests/manifest/testscript b/tests/manifest/testscript index d3fe1a7..b08206a 100644 --- a/tests/manifest/testscript +++ b/tests/manifest/testscript @@ -199,6 +199,7 @@ : location: http://pkg.example.org/1/bar role: prerequisite + trust: 37:CE:2C:A5:1D:CF:93:81:D7:07:46:AD:66:B3:C3:90:83:B8:96:9E:34:F0:E7:B3:A2:B0:6C:EF:66:A4:BE:65 : url: http://cppget.org EOI @@ -218,6 +219,8 @@ location: http://pkg.example.org/1/bar type: pkg role: prerequisite + trust: 37:CE:2C:A5:1D:CF:93:81:D7:07:46:AD:66:B3:C3:90:83:B8:96:9E:34:F0:E7:B\ + 3:A2:B0:6C:EF:66:A4:BE:65 : url: http://cppget.org EOO |