# # # patch "annotate.cc" # from [09b9fdcfd43d6ea5867e9a5b77e94dd39defbf9a] # to [aabab768147caacce00021d84c43fdb18970ff69] # # patch "cert.cc" # from [ee0f832e3b34cbb3fd6f701e09501a28bdc3643d] # to [45be1c684bf6e80c36e984f15d0878ab0a0c6b07] # # patch "cert.hh" # from [f5f5492ce2552c357e75c70f206e7a5c690901cb] # to [1c586eeb49d9897d1433babc355a6e771dfbcd9a] # # patch "cmd_list.cc" # from [03b36120c182624fc028fdd3303c1affec1876b0] # to [3557979a033d0b34331c21e84b1aac957ee4f8c4] # # patch "cmd_merging.cc" # from [a644ca4f6e45e2885224b6565835e81a76d7e729] # to [528f14816d3bcc0753cf36de625817299ed65be0] # # patch "database.cc" # from [92b6154a2180f68fd7681607eea565934b9ee518] # to [fdcf5835f73d6f9a7a94fd3da4db9c9555a15ff2] # # patch "database.hh" # from [3e4156e4f98fab98d384a0b3449c55dde501409e] # to [ea278da7a22de0dc196bd7ae8285d2de3dc4b1c7] # # patch "migrate_ancestry.cc" # from [ec057d749d84ef486c42b3cced77cd74e5f12034] # to [4dc87fb08f592d30bd238f40d2629f9e790511ab] # # patch "project.cc" # from [660e86dc61bb01e617617cfced6e2e8ee04af276] # to [3d508847354c1ab041a70ad04a994d8492f4c6a1] # # patch "project.hh" # from [78364423054750c92f48bee022e134a8d3abe640] # to [6514b20663b3ec51c4bab9794d2fd5548e5bb0ff] # # patch "rcs_import.cc" # from [7876d1609874f781297272a18fa35e7d28375d9e] # to [7ccb590276323894fa8236315ceba8fa49c26aac] # ============================================================ --- annotate.cc 09b9fdcfd43d6ea5867e9a5b77e94dd39defbf9a +++ annotate.cc aabab768147caacce00021d84c43fdb18970ff69 @@ -393,7 +393,7 @@ annotate_context::build_revisions_to_ann { vector< revision > certs; project.get_revision_certs(*i, certs); - erase_bogus_certs(project.db, certs); + project.db.erase_bogus_certs(certs); string author(cert_string_value(certs, author_cert_name, true, false, "@< ")); ============================================================ --- cert.cc ee0f832e3b34cbb3fd6f701e09501a28bdc3643d +++ cert.cc 45be1c684bf6e80c36e984f15d0878ab0a0c6b07 @@ -8,40 +8,14 @@ // PURPOSE. #include "base.hh" -#include -#include -#include "vector.hh" - -#include -#include -#include - -#include "lexical_cast.hh" #include "cert.hh" #include "constants.hh" -#include "database.hh" -#include "keys.hh" -#include "key_store.hh" #include "netio.hh" -#include "revision.hh" -#include "sanity.hh" #include "simplestring_xform.hh" #include "transforms.hh" -#include "vocab_cast.hh" -using std::make_pair; -using std::map; -using std::pair; -using std::set; using std::string; -using std::vector; -using std::remove_if; -using boost::shared_ptr; -using boost::get; -using boost::tuple; -using boost::lexical_cast; - // The alternaive is to #include "cert.hh" in vocab.*, which is even // uglier. @@ -55,170 +29,6 @@ template class manifest; template class revision; template class manifest; -// FIXME: the bogus-cert family of functions is ridiculous -// and needs to be replaced, or at least factored. - -struct -bogus_cert_p -{ - database & db; - bogus_cert_p(database & db) : db(db) {}; - - bool cert_is_bogus(cert const & c) const - { - cert_status status = check_cert(db, c); - if (status == cert_ok) - { - L(FL("cert ok")); - return false; - } - else if (status == cert_bad) - { - string txt; - cert_signable_text(c, txt); - W(F("ignoring bad signature by '%s' on '%s'") % c.key() % txt); - return true; - } - else - { - I(status == cert_unknown); - string txt; - cert_signable_text(c, txt); - W(F("ignoring unknown signature by '%s' on '%s'") % c.key() % txt); - return true; - } - } - - bool operator()(revision const & c) const - { - return cert_is_bogus(c.inner()); - } - - bool operator()(manifest const & c) const - { - return cert_is_bogus(c.inner()); - } -}; - -void -erase_bogus_certs(database & db, - vector< manifest > & certs) -{ - typedef vector< manifest >::iterator it; - it e = remove_if(certs.begin(), certs.end(), bogus_cert_p(db)); - certs.erase(e, certs.end()); - - vector< manifest > tmp_certs; - - // Sorry, this is a crazy data structure - typedef tuple< manifest_id, cert_name, cert_value > trust_key; - typedef map< trust_key, - pair< shared_ptr< set >, it > > trust_map; - trust_map trust; - - for (it i = certs.begin(); i != certs.end(); ++i) - { - trust_key key = trust_key(manifest_id(i->inner().ident.inner()), - i->inner().name, - i->inner().value); - trust_map::iterator j = trust.find(key); - shared_ptr< set > s; - if (j == trust.end()) - { - s.reset(new set()); - trust.insert(make_pair(key, make_pair(s, i))); - } - else - s = j->second.first; - s->insert(i->inner().key); - } - - for (trust_map::const_iterator i = trust.begin(); - i != trust.end(); ++i) - { - if (db.hook_get_manifest_cert_trust(*(i->second.first), - get<0>(i->first), - get<1>(i->first), - get<2>(i->first))) - { - if (global_sanity.debug_p()) - L(FL("trust function liked %d signers of %s cert on manifest %s") - % i->second.first->size() - % get<1>(i->first) - % get<0>(i->first)); - tmp_certs.push_back(*(i->second.second)); - } - else - { - W(F("trust function disliked %d signers of %s cert on manifest %s") - % i->second.first->size() - % get<1>(i->first) - % get<0>(i->first)); - } - } - certs = tmp_certs; -} - -void -erase_bogus_certs(database & db, - vector< revision > & certs) -{ - typedef vector< revision >::iterator it; - it e = remove_if(certs.begin(), certs.end(), bogus_cert_p(db)); - certs.erase(e, certs.end()); - - vector< revision > tmp_certs; - - // sorry, this is a crazy data structure - typedef tuple< revision_id, cert_name, cert_value > trust_key; - typedef map< trust_key, - pair< shared_ptr< set >, it > > trust_map; - trust_map trust; - - for (it i = certs.begin(); i != certs.end(); ++i) - { - trust_key key = trust_key(i->inner().ident, - i->inner().name, - i->inner().value); - trust_map::iterator j = trust.find(key); - shared_ptr< set > s; - if (j == trust.end()) - { - s.reset(new set()); - trust.insert(make_pair(key, make_pair(s, i))); - } - else - s = j->second.first; - s->insert(i->inner().key); - } - - for (trust_map::const_iterator i = trust.begin(); - i != trust.end(); ++i) - { - if (db.hook_get_revision_cert_trust(*(i->second.first), - get<0>(i->first), - get<1>(i->first), - get<2>(i->first))) - { - if (global_sanity.debug_p()) - L(FL("trust function liked %d signers of %s cert on revision %s") - % i->second.first->size() - % get<1>(i->first) - % get<0>(i->first)); - tmp_certs.push_back(*(i->second.second)); - } - else - { - W(F("trust function disliked %d signers of %s cert on revision %s") - % i->second.first->size() - % get<1>(i->first) - % get<0>(i->first)); - } - } - certs = tmp_certs; -} - - // cert-managing routines cert::cert(std::string const & s) { @@ -352,14 +162,6 @@ cert_hash_code(cert const & t, id & out) calculate_ident(tdat, out); } -cert_status -check_cert(database & db, cert const & t) -{ - string signed_text; - cert_signable_text(t, signed_text); - return db.check_signature(t.key, signed_text, t.sig); -} - // Local Variables: // mode: C++ // fill-column: 76 ============================================================ --- cert.hh f5f5492ce2552c357e75c70f206e7a5c690901cb +++ cert.hh 1c586eeb49d9897d1433babc355a6e771dfbcd9a @@ -10,12 +10,7 @@ #ifndef __CERT_HH__ #define __CERT_HH__ -#include -#include -#include "vector.hh" - #include "vocab.hh" -#include "dates.hh" // Certs associate an opaque name/value pair with a revision ID, and // are accompanied by an RSA public-key signature attesting to the @@ -23,27 +18,22 @@ // about revisions, using certs, without needing anyone's special // permission. -class key_store; -class database; -class project_t; -struct options; - struct cert : public origin_aware { cert() {} cert(revision_id const & ident, - cert_name const & name, - cert_value const & value, - rsa_keypair_id const & key) + cert_name const & name, + cert_value const & value, + rsa_keypair_id const & key) : ident(ident), name(name), value(value), key(key) {} cert(revision_id const & ident, - cert_name const & name, - cert_value const & value, - rsa_keypair_id const & key, - rsa_sha1_signature const & sig) + cert_name const & name, + cert_value const & value, + rsa_keypair_id const & key, + rsa_sha1_signature const & sig) : ident(ident), name(name), value(value), key(key), sig(sig) {} @@ -73,17 +63,7 @@ void cert_signable_text(cert const & t,s typedef enum {cert_ok, cert_bad, cert_unknown} cert_status; void cert_signable_text(cert const & t,std::string & out); -cert_status check_cert(database & db, cert const & t); -bool put_simple_revision_cert(database & db, - key_store & keys, - revision_id const & id, - cert_name const & nm, - cert_value const & val); - -void erase_bogus_certs(database & db, std::vector< revision > & certs); -void erase_bogus_certs(database & db, std::vector< manifest > & certs); - #endif // __CERT_HH__ // Local Variables: ============================================================ --- cmd_list.cc 03b36120c182624fc028fdd3303c1affec1876b0 +++ cmd_list.cc 3557979a033d0b34331c21e84b1aac957ee4f8c4 @@ -109,7 +109,7 @@ CMD(certs, "certs", "", CMD_REF(list), " for (size_t i = 0; i < certs.size(); ++i) { - cert_status status = check_cert(db, idx(certs, i)); + cert_status status = db.check_cert(idx(certs, i)); cert_value tv = idx(certs, i).value; string washed; if (guess_binary(tv())) @@ -822,7 +822,7 @@ CMD_AUTOMATE(certs, N_("REV"), for (size_t i = 0; i < certs.size(); ++i) { basic_io::stanza st; - cert_status status = check_cert(db, idx(certs, i)); + cert_status status = db.check_cert(idx(certs, i)); cert_value tv = idx(certs, i).value; cert_name name = idx(certs, i).name; set signers; ============================================================ --- cmd_merging.cc a644ca4f6e45e2885224b6565835e81a76d7e729 +++ cmd_merging.cc 528f14816d3bcc0753cf36de625817299ed65be0 @@ -96,7 +96,7 @@ pick_branch_for_update(options & opts, d // figure out which branches the target is in vector< revision > certs; db.get_revision_certs(chosen_rid, branch_cert_name, certs); - erase_bogus_certs(db, certs); + db.erase_bogus_certs(certs); set< branch_name > branches; for (vector< revision >::const_iterator i = certs.begin(); ============================================================ --- database.cc 92b6154a2180f68fd7681607eea565934b9ee518 +++ database.cc fdcf5835f73d6f9a7a94fd3da4db9c9555a15ff2 @@ -20,6 +20,8 @@ #include #include +#include +#include #include #include @@ -86,6 +88,9 @@ using boost::lexical_cast; using boost::shared_ptr; using boost::shared_dynamic_cast; using boost::lexical_cast; +using boost::get; +using boost::tuple; +using boost::lexical_cast; using Botan::PK_Encryptor; using Botan::PK_Verifier; @@ -3030,6 +3035,14 @@ database::check_signature(rsa_keypair_id return cert_bad; } +cert_status +database::check_cert(cert const & t) +{ + string signed_text; + cert_signable_text(t, signed_text); + return check_signature(t.key, signed_text, t.sig); +} + // cert management bool @@ -3403,6 +3416,168 @@ database::get_manifest_certs(cert_name c } +// FIXME: the bogus-cert family of functions is ridiculous +// and needs to be replaced, or at least factored. +namespace { + struct + bogus_cert_p + { + database & db; + bogus_cert_p(database & db) : db(db) {}; + + bool cert_is_bogus(cert const & c) const + { + cert_status status = db.check_cert(c); + if (status == cert_ok) + { + L(FL("cert ok")); + return false; + } + else if (status == cert_bad) + { + string txt; + cert_signable_text(c, txt); + W(F("ignoring bad signature by '%s' on '%s'") % c.key() % txt); + return true; + } + else + { + I(status == cert_unknown); + string txt; + cert_signable_text(c, txt); + W(F("ignoring unknown signature by '%s' on '%s'") % c.key() % txt); + return true; + } + } + + bool operator()(revision const & c) const + { + return cert_is_bogus(c.inner()); + } + + bool operator()(manifest const & c) const + { + return cert_is_bogus(c.inner()); + } + }; +} // anonymous namespace + +void +database::erase_bogus_certs(vector< manifest > & certs) +{ + typedef vector< manifest >::iterator it; + it e = remove_if(certs.begin(), certs.end(), bogus_cert_p(*this)); + certs.erase(e, certs.end()); + + vector< manifest > tmp_certs; + + // Sorry, this is a crazy data structure + typedef tuple< manifest_id, cert_name, cert_value > trust_key; + typedef map< trust_key, + pair< shared_ptr< set >, it > > trust_map; + trust_map trust; + + for (it i = certs.begin(); i != certs.end(); ++i) + { + trust_key key = trust_key(manifest_id(i->inner().ident.inner()), + i->inner().name, + i->inner().value); + trust_map::iterator j = trust.find(key); + shared_ptr< set > s; + if (j == trust.end()) + { + s.reset(new set()); + trust.insert(make_pair(key, make_pair(s, i))); + } + else + s = j->second.first; + s->insert(i->inner().key); + } + + for (trust_map::const_iterator i = trust.begin(); + i != trust.end(); ++i) + { + if (lua.hook_get_manifest_cert_trust(*(i->second.first), + get<0>(i->first), + get<1>(i->first), + get<2>(i->first))) + { + if (global_sanity.debug_p()) + L(FL("trust function liked %d signers of %s cert on manifest %s") + % i->second.first->size() + % get<1>(i->first) + % get<0>(i->first)); + tmp_certs.push_back(*(i->second.second)); + } + else + { + W(F("trust function disliked %d signers of %s cert on manifest %s") + % i->second.first->size() + % get<1>(i->first) + % get<0>(i->first)); + } + } + certs = tmp_certs; +} + +void +database::erase_bogus_certs(vector< revision > & certs) +{ + typedef vector< revision >::iterator it; + it e = remove_if(certs.begin(), certs.end(), bogus_cert_p(*this)); + certs.erase(e, certs.end()); + + vector< revision > tmp_certs; + + // sorry, this is a crazy data structure + typedef tuple< revision_id, cert_name, cert_value > trust_key; + typedef map< trust_key, + pair< shared_ptr< set >, it > > trust_map; + trust_map trust; + + for (it i = certs.begin(); i != certs.end(); ++i) + { + trust_key key = trust_key(i->inner().ident, + i->inner().name, + i->inner().value); + trust_map::iterator j = trust.find(key); + shared_ptr< set > s; + if (j == trust.end()) + { + s.reset(new set()); + trust.insert(make_pair(key, make_pair(s, i))); + } + else + s = j->second.first; + s->insert(i->inner().key); + } + + for (trust_map::const_iterator i = trust.begin(); + i != trust.end(); ++i) + { + if (lua.hook_get_revision_cert_trust(*(i->second.first), + get<0>(i->first), + get<1>(i->first), + get<2>(i->first))) + { + if (global_sanity.debug_p()) + L(FL("trust function liked %d signers of %s cert on revision %s") + % i->second.first->size() + % get<1>(i->first) + % get<0>(i->first)); + tmp_certs.push_back(*(i->second.second)); + } + else + { + W(F("trust function disliked %d signers of %s cert on revision %s") + % i->second.first->size() + % get<1>(i->first) + % get<0>(i->first)); + } + } + certs = tmp_certs; +} + // completions void database_impl::add_prefix_matching_constraint(string const & colname, @@ -3948,31 +4123,6 @@ database_impl::close() I(!__sql); } -// the database holds onto the lua_hooks object and uses it to re-expose -// these two hooks. it is impractical to pass the lua_hooks object down to -// all the places where this is used, and they're all going to get -// reexamined when we do policy branches anyway. also, arguably this is -// cleaner, because those places don't have access to *all* the lua hooks, -// just these two. (manifest cert trust is only relevant to pre-roster -// migration, but revision cert trust comes up everywhere erase_bogus_certs -// is called.) (A near-term refactor that might make sense: make -// erase_bogus_certs a project_t member and have the project_t hold the -// lua_hooks reference.) - -bool -database::hook_get_manifest_cert_trust(set const & signers, - manifest_id const & id, cert_name const & name, cert_value const & val) -{ - return lua.hook_get_manifest_cert_trust(signers, id, name, val); -}; - -bool -database::hook_get_revision_cert_trust(set const & signers, - revision_id const & id, cert_name const & name, cert_value const & val) -{ - return lua.hook_get_revision_cert_trust(signers, id, name, val); -}; - // transaction guards conditional_transaction_guard::~conditional_transaction_guard() ============================================================ --- database.hh 3e4156e4f98fab98d384a0b3449c55dde501409e +++ database.hh ea278da7a22de0dc196bd7ae8285d2de3dc4b1c7 @@ -254,6 +254,7 @@ public: cert_status check_signature(rsa_keypair_id const & id, std::string const & alleged_text, rsa_sha1_signature const & signature); + cert_status check_cert(cert const & t); // // --== Certs ==-- @@ -313,6 +314,9 @@ public: void get_manifest_certs(cert_name const & name, std::vector< manifest > & certs); + void erase_bogus_certs(std::vector< manifest > & certs); + void erase_bogus_certs(std::vector< revision > & certs); + // // --== Epochs ==-- // @@ -428,13 +432,6 @@ public: void put_roster_for_revision(revision_id const & new_id, revision_t const & rev); - // We make these lua hooks available via the database context; - // see comments above their definition for rationale and plans. - bool hook_get_manifest_cert_trust(std::set const & signers, - manifest_id const & id, cert_name const & name, cert_value const & val); - bool hook_get_revision_cert_trust(std::set const & signers, - revision_id const & id, cert_name const & name, cert_value const & val); - private: boost::shared_ptr imp; lua_hooks & lua; ============================================================ --- migrate_ancestry.cc ec057d749d84ef486c42b3cced77cd74e5f12034 +++ migrate_ancestry.cc 4dc87fb08f592d30bd238f40d2629f9e790511ab @@ -346,7 +346,7 @@ anc_graph::add_node_for_old_manifest(man // load certs vector< manifest > mcerts; db.get_manifest_certs(man, mcerts); - erase_bogus_certs(db, mcerts); + db.erase_bogus_certs(mcerts); for(vector< manifest >::const_iterator i = mcerts.begin(); i != mcerts.end(); ++i) { @@ -389,7 +389,7 @@ u64 anc_graph::add_node_for_oldstyle_rev // load certs vector< revision > rcerts; db.get_revision_certs(rev, rcerts); - erase_bogus_certs(db, rcerts); + db.erase_bogus_certs(rcerts); for(vector< revision >::const_iterator i = rcerts.begin(); i != rcerts.end(); ++i) { @@ -947,7 +947,7 @@ build_changesets_from_manifest_ancestry( vector< manifest > tmp; db.get_manifest_certs(cert_name("ancestor"), tmp); - erase_bogus_certs(db, tmp); + db.erase_bogus_certs(tmp); for (vector< manifest >::const_iterator i = tmp.begin(); i != tmp.end(); ++i) ============================================================ --- project.cc 660e86dc61bb01e617617cfced6e2e8ee04af276 +++ project.cc 3d508847354c1ab041a70ad04a994d8492f4c6a1 @@ -105,7 +105,7 @@ namespace cert_name(branch_cert_name), typecast_vocab(branch), certs); - erase_bogus_certs(db, certs); + db.erase_bogus_certs(certs); return certs.empty(); } }; @@ -125,7 +125,7 @@ namespace cert_name(suspend_cert_name), typecast_vocab(branch), certs); - erase_bogus_certs(db, certs); + db.erase_bogus_certs(certs); return !certs.empty(); } }; @@ -180,7 +180,7 @@ project_t::revision_is_in_branch(revisio int num = certs.size(); - erase_bogus_certs(db, certs); + db.erase_bogus_certs(certs); L(FL("found %d (%d valid) %s branch certs on revision %s") % num @@ -209,7 +209,7 @@ project_t::revision_is_suspended_in_bran int num = certs.size(); - erase_bogus_certs(db, certs); + db.erase_bogus_certs(certs); L(FL("found %d (%d valid) %s suspend certs on revision %s") % num @@ -249,7 +249,7 @@ project_t::get_revision_certs_by_name(re std::vector > & certs) { outdated_indicator i = db.get_revision_certs(id, name, certs); - erase_bogus_certs(db, certs); + db.erase_bogus_certs(certs); return i; } @@ -304,7 +304,7 @@ project_t::get_tags(set & tags) { std::vector > certs; outdated_indicator i = db.get_revision_certs(tag_cert_name, certs); - erase_bogus_certs(db, certs); + db.erase_bogus_certs(certs); tags.clear(); for (std::vector >::const_iterator i = certs.begin(); i != certs.end(); ++i) ============================================================ --- project.hh 78364423054750c92f48bee022e134a8d3abe640 +++ project.hh 6514b20663b3ec51c4bab9794d2fd5548e5bb0ff @@ -22,6 +22,7 @@ struct globish; class options; class lua_hooks; struct globish; +struct date_t; // "Special" certs have syntax and semantics essential to correct operation. // They add structure to the ancestry graph. ============================================================ --- rcs_import.cc 7876d1609874f781297272a18fa35e7d28375d9e +++ rcs_import.cc 7ccb590276323894fa8236315ceba8fa49c26aac @@ -28,6 +28,7 @@ #include "constants.hh" #include "cycle_detector.hh" #include "database.hh" +#include "dates.hh" #include "file_io.hh" #include "interner.hh" #include "paths.hh"