aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2016-04-29 10:07:03 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2016-05-04 20:37:44 +0300
commit057a5d5d435d53166d1b8751748a9ba0a317bee3 (patch)
tree6770b5ba1566c95e79ad73e845ac4a04c145cbec
parentd61e9338c8eda118c5f2afd93827be4a84bdc36a (diff)
Add signature_manifest class
-rw-r--r--NEWS7
-rw-r--r--bpkg/manifest33
-rw-r--r--bpkg/manifest.cxx96
-rw-r--r--tests/manifest/.gitignore1
-rw-r--r--tests/manifest/buildfile10
-rw-r--r--tests/manifest/driver.cxx4
-rw-r--r--tests/manifest/signature13
7 files changed, 158 insertions, 6 deletions
diff --git a/NEWS b/NEWS
index b1e2143..f733de5 100644
--- a/NEWS
+++ b/NEWS
@@ -1,10 +1,15 @@
+Version 0.4.0
+
+ * Add signature_manifest class.
+
+ * Add repository_manifest::certificate.
+
Version 0.3.0
* Reimplement *-file manifest values as C++11 unions.
* Add support for comments in the repository manifest email values.
-
Version 0.2.0
* First public release.
diff --git a/bpkg/manifest b/bpkg/manifest
index d55e714..0c9362f 100644
--- a/bpkg/manifest
+++ b/bpkg/manifest
@@ -588,6 +588,39 @@ namespace bpkg
void
serialize (manifest_serializer&) const;
};
+
+ class signature_manifest
+ {
+ public:
+ // Checksum of the corresponding package_manifests.
+ //
+ std::string sha256sum;
+
+ // Signature of the corresponding package_manifests. Calculated by
+ // encrypting package_manifests checksum (stored in sha256sum) with the
+ // repository certificate private key.
+ //
+ std::vector<char> signature;
+
+ public:
+ signature_manifest () = default;
+ signature_manifest (manifest_parser&, bool ignore_unknown = false);
+
+ // Serialize sha256sum and base64-encoded representation of the signature.
+ //
+ void
+ serialize (manifest_serializer&) const;
+
+ private:
+ // Used for delegating in public constructor. Strictly speaking is not
+ // required, as a signature_manifest currently never appears as a part of
+ // a manifest list, but kept for the consistency with other manifests
+ // implementations.
+ //
+ signature_manifest (manifest_parser&,
+ manifest_name_value start,
+ bool ignore_unknown);
+ };
}
#endif // BPKG_MANIFEST
diff --git a/bpkg/manifest.cxx b/bpkg/manifest.cxx
index b94c2c6..ff1c88f 100644
--- a/bpkg/manifest.cxx
+++ b/bpkg/manifest.cxx
@@ -18,6 +18,7 @@
#include <stdexcept> // invalid_argument
#include <butl/path>
+#include <butl/base64>
#include <bpkg/manifest-parser>
#include <bpkg/manifest-serializer>
@@ -1197,7 +1198,7 @@ namespace bpkg
{
// @@ Should we check that all non-optional values are specified ?
// @@ Should we check that values are valid: name is not empty, version
- // release is not empty, sha256sum is a proper string, ...
+ // release is not empty, sha256sum is a proper string, ...?
// @@ Currently we don't know if we are serializing the individual package
// manifest or the package list manifest, so can't ensure all values
// allowed in the current context (location, sha256sum, *-file values).
@@ -2072,4 +2073,97 @@ namespace bpkg
s.next ("", ""); // End of stream.
}
+
+ // signature_manifest
+ //
+ signature_manifest::
+ signature_manifest (parser& p, bool iu)
+ : signature_manifest (p, p.next (), iu) // Delegate
+ {
+ // Make sure this is the end.
+ //
+ name_value nv (p.next ());
+ if (!nv.empty ())
+ throw parsing (p.name (), nv.name_line, nv.name_column,
+ "single signature manifest expected");
+ }
+
+ signature_manifest::
+ signature_manifest (parser& p, name_value nv, bool iu)
+ {
+ auto bad_name ([&p, &nv](const string& d) {
+ throw parsing (p.name (), nv.name_line, nv.name_column, d);});
+
+ auto bad_value ([&p, &nv](const string& d) {
+ throw parsing (p.name (), nv.value_line, nv.value_column, d);});
+
+ // Make sure this is the start and we support the version.
+ //
+ if (!nv.name.empty ())
+ bad_name ("start of signature manifest expected");
+
+ if (nv.value != "1")
+ bad_value ("unsupported format version");
+
+ for (nv = p.next (); !nv.empty (); nv = p.next ())
+ {
+ string& n (nv.name);
+ string& v (nv.value);
+
+ if (n == "sha256sum")
+ {
+ if (!sha256sum.empty ())
+ bad_name ("sha256sum redefinition");
+
+ if (v.empty ())
+ bad_value ("empty sha256sum");
+
+ if (!valid_sha256 (v))
+ bad_value ("invalid sha256sum");
+
+ sha256sum = move (v);
+ }
+ else if (n == "signature")
+ {
+ if (!signature.empty ())
+ bad_name ("signature redefinition");
+
+ if (v.empty ())
+ bad_value ("empty signature");
+
+ // Try to base64-decode as a sanity check.
+ //
+ try
+ {
+ signature = base64_decode (v);
+ }
+ catch (const invalid_argument&)
+ {
+ bad_value ("invalid signature");
+ }
+ }
+ else if (!iu)
+ bad_name ("unknown name '" + n + "' in signature manifest");
+ }
+
+ // Verify all non-optional values were specified.
+ //
+ if (sha256sum.empty ())
+ bad_value ("no sha256sum specified");
+ else if (signature.empty ())
+ bad_value ("no signature specified");
+ }
+
+ void signature_manifest::
+ serialize (serializer& s) const
+ {
+ // @@ Should we check that values are valid ?
+ //
+ s.next ("", "1"); // Start of manifest.
+
+ s.next ("sha256sum", sha256sum);
+ s.next ("signature", base64_encode (signature));
+
+ s.next ("", ""); // End of manifest.
+ }
}
diff --git a/tests/manifest/.gitignore b/tests/manifest/.gitignore
index d0bb148..d9c2bbc 100644
--- a/tests/manifest/.gitignore
+++ b/tests/manifest/.gitignore
@@ -1,2 +1,3 @@
pdriver
rdriver
+sdriver
diff --git a/tests/manifest/buildfile b/tests/manifest/buildfile
index 0696a1c..c417a08 100644
--- a/tests/manifest/buildfile
+++ b/tests/manifest/buildfile
@@ -7,7 +7,7 @@
# @@ Hack until build2 supports multiple tests. Also remove .gitignore.
#
-./: exe{pdriver} exe{rdriver}
+./: exe{pdriver} exe{rdriver} exe{sdriver}
exe{pdriver}: obj{pdriver}
exe{pdriver}: test.roundtrip = packages
@@ -15,10 +15,14 @@ exe{pdriver}: test.roundtrip = packages
exe{rdriver}: obj{rdriver}
exe{rdriver}: test.roundtrip = repositories
-obj{pdriver rdriver}: cxx{driver}
-exe{pdriver rdriver} obj{pdriver rdriver}: ../../bpkg/lib{bpkg}
+exe{sdriver}: obj{sdriver}
+exe{sdriver}: test.roundtrip = signature
+
+obj{pdriver rdriver sdriver}: cxx{driver}
+exe{pdriver rdriver sdriver} obj{pdriver rdriver sdriver}: ../../bpkg/lib{bpkg}
obj{pdriver}: cxx.poptions += -DTEST_PACKAGES
obj{rdriver}: cxx.poptions += -DTEST_REPOSITORIES
+obj{sdriver}: cxx.poptions += -DTEST_SIGNATURE
include ../../bpkg/
diff --git a/tests/manifest/driver.cxx b/tests/manifest/driver.cxx
index e9551ae..c153477 100644
--- a/tests/manifest/driver.cxx
+++ b/tests/manifest/driver.cxx
@@ -31,8 +31,10 @@ main (int argc, char* argv[])
#ifdef TEST_PACKAGES
package_manifests ms (p);
-#else
+#elif TEST_REPOSITORIES
repository_manifests ms (p);
+#else
+ signature_manifest ms (p);
#endif
manifest_serializer s (cout, "stdout");
diff --git a/tests/manifest/signature b/tests/manifest/signature
new file mode 100644
index 0000000..5a83eeb
--- /dev/null
+++ b/tests/manifest/signature
@@ -0,0 +1,13 @@
+: 1
+sha256sum: a2b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
+signature: \
+geWdw7Gm+Rt+CLDMBby5Y796E8rxwImb0bmcZwGWar9D3vkFm9Kjh00Buuo1PuU7tP1dV6yvRbH8
+NzC0IryEoUJHx9909AJ449ET9Zb+C3ykEeBlKH2wonj7cAVK9ZEDpPEGAtp56XWZQEawl50mwq6t
+XkZAABxtOswXiicdh3HK7kaPHp38/9CBMc0rva6wDnkbTigUYA2ULqLtP5a5mLovVc48zI9A/hmb
+Qx1/Nr7nzTZNDGK7CwTAb1fPam9rZklTfCTPSPUUjvWjM9XdY8cbRE1FrE14TXdyQPxCLzHO2dUO
+YWH5/qMikEoCYhYXQ6KhekoT/MUiVC3PMcYQbYOrOtSxq6RcgnymexBe1XIyld5Rfo1eXu8TK11r
+QPULIqAGy6RwEUhGznuEiGHQwb1UymNyJ/qgr4vBPjJtlvptqG5XNmtiJ22f07nmeVRi2Vg2UyOw
+HoVpy5t/w0tEnUXPA39Vt0v1bUm7Knhc8qL4JFEqK/j/CzEHzEtAjn0aoGuKubCO0WUa+v6ZlkLU
+YrNUIdgT1wgj4yEhLO3g+NsnxFH05D2sfR16rrkI2E6st5crAHR8FOl2FDsWxgKqNbzXZw7rl+Fa
+TobGycX7MDf2mbBmR/KmEkMBJ4mziWLAycSAGyE5VRYDwHPJlQE0143wBzT8eNw4VLm/r+88VYw=
+\