# # # patch "cert.cc" # from [7085104c5883eac077e0aec090559279b25a7bff] # to [eb7ef42d28821a382223da9e1b85eb68a56f80ef] # # patch "cert.hh" # from [a4a81eb418cd6a9ac0d79c47ab2376a9fe2a1999] # to [5b7ab6dff38e0ba62f74f87fc621357a7703a0ae] # # patch "netsync.cc" # from [993bfd387d60a57bd06843d6ebb1f5521cca5575] # to [99a29627477839f243d31cdb71a2b8af5705be40] # ============================================================ --- cert.cc 7085104c5883eac077e0aec090559279b25a7bff +++ cert.cc eb7ef42d28821a382223da9e1b85eb68a56f80ef @@ -42,9 +42,11 @@ cert::operator==(cert const & other) con } // netio support +enum read_cert_version {read_cert_v6, read_cert_current}; -static void -read_cert(database & db, string const & in, cert & t) +static bool +read_cert(database & db, string const & in, cert & t, + read_cert_version ver) { size_t pos = 0; id hash = id(extract_substring(in, pos, @@ -62,11 +64,52 @@ read_cert(database & db, string const & extract_variable_length_string(in, sig, pos, "cert sig"); assert_end_of_buffer(in, pos, "cert"); - cert tmp(ident, cert_name(name, origin::network), - cert_value(val, origin::network), - key_id(key, origin::network), - rsa_sha1_signature(sig, origin::network)); + cert tmp; + tmp.ident = ident; + tmp.name = cert_name(name, origin::network); + tmp.value = cert_value(val, origin::network); + tmp.sig = rsa_sha1_signature(sig, origin::network); + string signable; + tmp.signable_text(signable); + key_id keyid; + switch(ver) + { + case read_cert_v6: + { + bool found = false; + std::vector all_keys; + db.get_key_ids(all_keys); + for (std::vector::const_iterator i = all_keys.begin(); + i != all_keys.end(); ++i) + { + key_name keyname; + rsa_pub_key pub; + db.get_pubkey(*i, keyname, pub); + if (keyname() == key) + { + if(db.check_signature(*i, signable, tmp.sig) == cert_ok) + { + tmp.key = *i; + found = true; + break; + } + } + } + if (!found) + { + W(F("Cannot find appropriate key '%s' for old-style cert") + % name); + return false; + } + } + break; + case read_cert_current: + tmp.key = key_id(key, origin::network); + break; + default: + I(false); + } key_name keyname; rsa_pub_key junk; @@ -78,17 +121,23 @@ read_cert(database & db, string const & throw bad_decode(F("calculated cert hash '%s' does not match '%s'") % check % hash); t = tmp; + return true; } -cert::cert(database & db, std::string const & s) +bool cert::read_cert_v6(database & db, std::string const & s, cert & c) { - read_cert(db, s, *this); + return ::read_cert(db, s, c, ::read_cert_v6); } +bool cert::read_cert(database & db, std::string const & s, cert & c) +{ + return ::read_cert(db, s, c, read_cert_current); +} + cert::cert(database & db, std::string const & s, origin::type m) : origin_aware(m) { - read_cert(db, s, *this); + ::read_cert(db, s, *this, read_cert_current); } void @@ -106,6 +155,20 @@ void } void +cert::marshal_for_netio_v6(key_name const & keyname, string & out) const +{ + id hash; + hash_code(keyname, hash); + + out.append(hash()); + out.append(this->ident.inner()()); + insert_variable_length_string(this->name(), out); + insert_variable_length_string(this->value(), out); + insert_variable_length_string(keyname(), out); + insert_variable_length_string(this->sig(), out); +} + +void cert::signable_text(string & out) const { base64 val_encoded(encode_base64(this->value)); ============================================================ --- cert.hh a4a81eb418cd6a9ac0d79c47ab2376a9fe2a1999 +++ cert.hh 5b7ab6dff38e0ba62f74f87fc621357a7703a0ae @@ -40,7 +40,8 @@ struct cert : public origin_aware {} // These understand the netsync serialization. - cert(database & db, std::string const & s); + static bool read_cert(database & db, std::string const & s, cert & c); + static bool read_cert_v6(database & db, std::string const & s, cert & c); cert(database & db, std::string const & s, origin::type m); revision_id ident; @@ -55,6 +56,7 @@ struct cert : public origin_aware void hash_code(key_name const & keyname, id & out) const; void signable_text(std::string & out) const; void marshal_for_netio(key_name const & keyname, std::string & out) const; + void marshal_for_netio_v6(key_name const & keyname, std::string & out) const; }; #endif // __CERT_HH__ ============================================================ --- netsync.cc 993bfd387d60a57bd06843d6ebb1f5521cca5575 +++ netsync.cc 99a29627477839f243d31cdb71a2b8af5705be40 @@ -2267,7 +2267,14 @@ session::load_data(netcmd_item_type type key_name keyname; rsa_pub_key junk; project.db.get_pubkey(c.key, keyname, junk); - c.marshal_for_netio(keyname, out); + if (version >= 7) + { + c.marshal_for_netio(keyname, out); + } + else + { + c.marshal_for_netio_v6(keyname, out); + } } break; } @@ -2365,16 +2372,29 @@ session::process_data_cmd(netcmd_item_ty case cert_item: { - cert c(project.db, dat); - key_name keyname; - rsa_pub_key junk; - project.db.get_pubkey(c.key, keyname, junk); - id tmp; - c.hash_code(keyname, tmp); - if (! (tmp == item)) - throw bad_decode(F("hash check failed for revision cert '%s'") % hitem()); - if (project.db.put_revision_cert(c)) - written_certs.push_back(c); + cert c; + bool matched; + if (version >= 7) + { + matched = cert::read_cert(project.db, dat, c); + } + else + { + matched = cert::read_cert_v6(project.db, dat, c); + } + + if (matched) + { + key_name keyname; + rsa_pub_key junk; + project.db.get_pubkey(c.key, keyname, junk); + id tmp; + c.hash_code(keyname, tmp); + if (! (tmp == item)) + throw bad_decode(F("hash check failed for revision cert '%s'") % hitem()); + if (project.db.put_revision_cert(c)) + written_certs.push_back(c); + } } break;