# # # patch "annotate.cc" # from [26a161ceac97a36cde42e45e36e65c849b99e341] # to [286e76ebf6fb53254e44f933eaa169b3427a32ad] # # patch "cmd_db.cc" # from [2136c59206225d79e5777b76efe07f07c09a9aba] # to [67a93c17c35f12616e8a033a8d1a8421adf0e313] # # patch "cmd_key_cert.cc" # from [ec22023ddd85b5c087bdbd2bed3443a68fe6b1dd] # to [403bf9449641a185318b6e1596f000993c8b432c] # # patch "cmd_list.cc" # from [24c43dd8c6b74277b6787ce6d648248c382fe788] # to [c6a2bd7276a638e023a24512c95d1e692b0b449c] # # patch "cmd_merging.cc" # from [29eff72564c06e9f8807160563fb1d0adfc32d3f] # to [74dfe4ceeec6e3ca0f520490aaaa5f5d357871fe] # # patch "cmd_packet.cc" # from [1e8889a5d1085ae2c364f5d58f2bdb16b7d5bea4] # to [5ec955dd63ebd48c72941ac103deafa0e1859e22] # # patch "database.cc" # from [8b1be269c38db9eda1da27a8381c7af6a117bbdb] # to [4c84483c9169b3b7abca88dc1392b860b54e6411] # # patch "database.hh" # from [fac63cd36816f326106c19fd56bd2e1b8246510c] # to [e051b0dd5eca6894ae8bfc7a734d04f2ca7c7c52] # # patch "key_store.cc" # from [63bc362c154f9927410c87a2c1312cfe2c4520ca] # to [cccb570b37409c34036e52f908a7246904d46337] # # patch "keys.cc" # from [c0a07b4c39c1ea1591d8694351659d3a4a5428bd] # to [f33f7007716e34467de1b15b300c268bf9762526] # # patch "lua_hooks.cc" # from [e5659dd576008ff3c863a27de3bcbda1bdad0186] # to [0a577a8ec34e3ccf46d9643bfd42a0fad63e3838] # # patch "lua_hooks.hh" # from [1d3b092d2abe0ab21fb41c5ccc22417cd5c7e6d0] # to [11905d6000abba47120174668fe2b28aa2608b2b] # # patch "migrate_ancestry.cc" # from [bee80cc0f2ac2e39fba08bfbf759717665cdbe7f] # to [60a55508a8a2e7dcbcea9f22ad19b8e1a0f8885c] # # patch "migration.hh" # from [eddb224da22ddb812472fde688ca4ae8ce21bbeb] # to [3dad1bb7ccc5d4cca2941b8a650770febeada6e0] # # patch "netsync.cc" # from [632825f399ff0e1ef520b38fb8b2730606a20735] # to [fdc4cfa42234b01adfc25b5c4f57d603da54faf7] # # patch "options_list.hh" # from [8a6808b055bed17d11f2c61924df3b73353f6a80] # to [dea0f08761112a3113a14a9f903b66faad4f02eb] # # patch "project.cc" # from [ead04f0d92d9364504b2a8cb93801c8a17a5984a] # to [3cf74cf70e55f430c08a27bc46c524ecd1b30e15] # # patch "project.hh" # from [0f53d807f622042c42a122866919c755bf8b3b2a] # to [3bc274753337aca0aa14d1fbb8320abd923fda04] # # patch "std_hooks.lua" # from [c9dd3ea46238ea2899e6d450154bca73f971547b] # to [b0441ca2a69efe33d7df879dabd52019bb2bf42f] # # patch "tests/test_hooks.lua" # from [33fa5ede0f6a84f7b4d8c2432a45e135ac5af936] # to [d8e009b5e2c7d00afe4b301d60b8242936d6b794] # # patch "work.cc" # from [925e839ec6e1ced6f9345dece76ee2d02a6fd526] # to [9053a57ad3260c1c6f54e3b8aa038006b71e0119] # ============================================================ --- annotate.cc 26a161ceac97a36cde42e45e36e65c849b99e341 +++ annotate.cc 286e76ebf6fb53254e44f933eaa169b3427a32ad @@ -393,7 +393,7 @@ annotate_context::build_revisions_to_ann { vector certs; project.get_revision_certs(*i, certs); - project.db.erase_bogus_certs(certs); + project.db.erase_bogus_certs(project, certs); string author(cert_string_value(certs, author_cert_name, true, false, "@< ")); ============================================================ --- cmd_db.cc 2136c59206225d79e5777b76efe07f07c09a9aba +++ cmd_db.cc 67a93c17c35f12616e8a033a8d1a8421adf0e313 @@ -278,7 +278,7 @@ CMD(db_changesetify, "changesetify", "", // early short-circuit to avoid failure after lots of work cache_user_key(app.opts, app.lua, db, keys, project); - build_changesets_from_manifest_ancestry(db, keys, set()); + build_changesets_from_manifest_ancestry(db, keys, project, set()); } CMD(db_rosterify, "rosterify", "", CMD_REF(db), "", @@ -299,7 +299,7 @@ CMD(db_rosterify, "rosterify", "", CMD_R // early short-circuit to avoid failure after lots of work cache_user_key(app.opts, app.lua, db, keys, project); - build_roster_style_revs_from_manifest_style_revs(db, keys, + build_roster_style_revs_from_manifest_style_revs(db, keys, project, app.opts.attrs_to_drop); } ============================================================ --- cmd_key_cert.cc ec22023ddd85b5c087bdbd2bed3443a68fe6b1dd +++ cmd_key_cert.cc 403bf9449641a185318b6e1596f000993c8b432c @@ -59,29 +59,27 @@ CMD(dropkey, "dropkey", "", CMD_REF(key_ if (args.size() != 1) throw usage(execid); - key_id ident; + key_identity_info identity; project_t project(db); - project.lookup_key_by_name(keys, - typecast_vocab(idx(args, 0)), - ident); + project.get_key_identity(keys, idx(args, 0), identity); if (db.database_specified()) { transaction_guard guard(db); - if (db.public_key_exists(ident)) + if (db.public_key_exists(identity.id)) { - P(F("dropping public key '%s' from database") % ident); - db.delete_public_key(ident); + P(F("dropping public key '%s' from database") % identity.id); + db.delete_public_key(identity.id); key_deleted = true; } guard.commit(); checked_db = true; } - if (keys.key_pair_exists(ident)) + if (keys.key_pair_exists(identity.id)) { - P(F("dropping key pair '%s' from keystore") % ident); - keys.delete_key(ident); + P(F("dropping key pair '%s' from keystore") % identity.id); + keys.delete_key(identity.id); key_deleted = true; } @@ -201,6 +199,7 @@ CMD(trusted, "trusted", "", CMD_REF(key_ N_("The current settings are used to run the test."), options::opts::none) { + key_store keys(app); // so the user can name keys that aren't in the db database db(app); project_t project(db); @@ -220,10 +219,12 @@ CMD(trusted, "trusted", "", CMD_REF(key_ cert_value value = typecast_vocab(idx(args, 2)); - set signers; + set signers; for (unsigned int i = 3; i != args.size(); ++i) { - signers.insert(decode_hexenc_as(idx(args, i)(), origin::user)); + key_identity_info identity; + project.get_key_identity(keys, idx(args, i), identity); + signers.insert(identity); } @@ -234,7 +235,7 @@ CMD(trusted, "trusted", "", CMD_REF(key_ ostringstream all_signers; copy(signers.begin(), signers.end(), - ostream_iterator(all_signers, " ")); + ostream_iterator(all_signers, " ")); cout << (F("if a cert on: %s\n" "with key: %s\n" ============================================================ --- cmd_list.cc 24c43dd8c6b74277b6787ce6d648248c382fe788 +++ cmd_list.cc c6a2bd7276a638e023a24512c95d1e692b0b449c @@ -140,13 +140,13 @@ CMD(certs, "certs", "", CMD_REF(list), " split_into_lines(washed, lines); std::string value_first_line = lines.empty() ? "" : idx(lines, 0); - key_id keyid = idx(certs, i).key; - key_name keyname; - project.get_name_of_key(keys, keyid, keyname); + key_identity_info identity; + identity.id = idx(certs, i).key; + project.complete_key_identity(keys, identity); cout << string(guess_terminal_width(), '-') << '\n' << (i18n_format(str) - % keyid % keyname + % identity.id % identity.official_name % stat % idx(certs, i).name % value_first_line); @@ -279,12 +279,11 @@ namespace { for (vector::iterator i = dbkeys.begin(); i != dbkeys.end(); i++) { - key_name name; - project.get_canonical_name_of_key(keys, *i, name); - items[*i].get<0>() = name(); - key_name alias; - project.get_name_of_key(keys, *i, alias); - items[*i].get<1>() = alias(); + key_identity_info identity; + identity.id = *i; + project.complete_key_identity(identity); + items[*i].get<0>() = identity.official_name(); + items[*i].get<1>() = identity.given_name(); items[*i].get<2>().push_back("database"); } } @@ -295,12 +294,11 @@ namespace { for (vector::iterator i = kskeys.begin(); i != kskeys.end(); i++) { - key_name name; - project.get_canonical_name_of_key(keys, *i, name); - items[*i].get<0>() = name(); - key_name alias; - project.get_name_of_key(keys, *i, alias); - items[*i].get<1>() = alias(); + key_identity_info identity; + identity.id = *i; + project.complete_key_identity(keys, identity); + items[*i].get<0>() = identity.official_name(); + items[*i].get<1>() = identity.given_name(); items[*i].get<2>().push_back("keystore"); items[*i].get<3>().push_back("keystore"); } @@ -853,17 +851,19 @@ CMD_AUTOMATE(certs, N_("REV"), 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; + set signers; - key_id keyid = idx(certs, i).key; - signers.insert(keyid); + key_identity_info identity; + identity.id = idx(certs, i).key; + project.complete_key_identity(identity); + signers.insert(identity); bool trusted = app.lua.hook_get_revision_cert_trust(signers, rid.inner(), name, tv); hexenc keyid_enc; - encode_hexenc(keyid.inner(), keyid_enc); + encode_hexenc(identity.id.inner(), keyid_enc); st.push_hex_pair(syms::key, keyid_enc); string stat; ============================================================ --- cmd_merging.cc 29eff72564c06e9f8807160563fb1d0adfc32d3f +++ cmd_merging.cc 74dfe4ceeec6e3ca0f520490aaaa5f5d357871fe @@ -125,14 +125,15 @@ static bool } static bool -pick_branch_for_update(options & opts, database & db, revision_id chosen_rid) +pick_branch_for_update(options & opts, database & db, + project_t & project, revision_id chosen_rid) { bool switched_branch = false; // figure out which branches the target is in vector certs; db.get_revision_certs(chosen_rid, branch_cert_name, certs); - db.erase_bogus_certs(certs); + db.erase_bogus_certs(project, certs); set< branch_name > branches; for (vector::const_iterator i = certs.begin(); @@ -258,7 +259,7 @@ CMD(update, "update", "", CMD_REF(worksp // Fiddle around with branches, in an attempt to guess what the user // wants. - bool switched_branch = pick_branch_for_update(app.opts, db, chosen_rid); + bool switched_branch = pick_branch_for_update(app.opts, db, project, chosen_rid); if (switched_branch) P(F("switching to branch %s") % app.opts.branch()); ============================================================ --- cmd_packet.cc 1e8889a5d1085ae2c364f5d58f2bdb16b7d5bea4 +++ cmd_packet.cc 5ec955dd63ebd48c72941ac103deafa0e1859e22 @@ -29,28 +29,26 @@ CMD(pubkey, "pubkey", "", CMD_REF(packet "", options::opts::none) { - database db(app); - key_store keys(app); - if (args.size() != 1) throw usage(execid); - key_id ident; + database db(app); + key_store keys(app); project_t project(db); - project.lookup_key_by_name(keys, - typecast_vocab(idx(args, 0)), - ident); + + key_identity_info identity; + project.get_key_identity(keys, idx(args, 0), identity); bool exists(false); rsa_pub_key key; - if (db.database_specified() && db.public_key_exists(ident)) + if (db.database_specified() && db.public_key_exists(identity.id)) { - db.get_key(ident, key); + db.get_key(identity.id, key); exists = true; } - if (keys.key_pair_exists(ident)) + if (keys.key_pair_exists(identity.id)) { keypair kp; - keys.get_key_pair(ident, kp); + keys.get_key_pair(identity.id, kp); key = kp.pub; exists = true; } @@ -58,9 +56,7 @@ CMD(pubkey, "pubkey", "", CMD_REF(packet F("public key '%s' does not exist") % idx(args, 0)()); packet_writer pw(cout); - key_name canonical_name; - project.get_canonical_name_of_key(keys, ident, canonical_name); - pw.consume_public_key(canonical_name, key); + pw.consume_public_key(identity.given_name, key); } CMD(privkey, "privkey", "", CMD_REF(packet_io), N_("ID"), @@ -76,16 +72,16 @@ CMD(privkey, "privkey", "", CMD_REF(pack throw usage(execid); key_name name = typecast_vocab(idx(args, 0)); - key_id ident; - project.lookup_key_by_name(keys, name, ident); - E(keys.key_pair_exists(ident), origin::user, + key_identity_info identity; + project.get_key_identity(idx(args, 0), identity); + E(keys.key_pair_exists(identity.id), origin::user, F("public and private key '%s' do not exist in keystore") % idx(args, 0)()); packet_writer pw(cout); keypair kp; key_name given_name; - keys.get_key_pair(ident, given_name, kp); + keys.get_key_pair(identity.id, given_name, kp); pw.consume_key_pair(given_name, kp); } ============================================================ --- database.cc 8b1be269c38db9eda1da27a8381c7af6a117bbdb +++ database.cc 4c84483c9169b3b7abca88dc1392b860b54e6411 @@ -3573,14 +3573,58 @@ namespace { } certs = tmp_certs; } + // the lua hook wants key_identity_info, but all that's been + // pulled from the certs is key_id. So this is needed to translate. + // use pointers for project and lua so bind() doesn't make copies + bool check_revision_cert_trust(project_t * const project, + lua_hooks * const lua, + set const & signers, + id const & hash, + cert_name const & name, + cert_value const & value) + { + set signer_identities; + for (set::const_iterator i = signers.begin(); + i != signers.end(); ++i) + { + key_identity_info identity; + identity.id = *i; + project->complete_key_identity(identity); + signer_identities.insert(identity); + } + + return lua->hook_get_revision_cert_trust(signer_identities, + hash, name, value); + } + // and the lua hook for manifest trust checking wants a key_name + bool check_manifest_cert_trust(database * const db, + lua_hooks * const lua, + set const & signers, + id const & hash, + cert_name const & name, + cert_value const & value) + { + set signer_names; + for (set::const_iterator i = signers.begin(); + i != signers.end(); ++i) + { + key_name name; + rsa_pub_key pub; + db->get_pubkey(*i, name, pub); + signer_names.insert(name); + } + + return lua->hook_get_manifest_cert_trust(signer_names, + hash, name, value); + } } // anonymous namespace void -database::erase_bogus_certs(vector & certs) +database::erase_bogus_certs(project_t & project, vector & certs) { erase_bogus_certs_internal(certs, *this, - boost::bind(&lua_hooks::hook_get_revision_cert_trust, - &this->lua, _1, _2, _3, _4)); + boost::bind(&check_revision_cert_trust, + &project, &this->lua, _1, _2, _3, _4)); } void database::erase_bogus_certs(vector & certs, @@ -3598,8 +3642,8 @@ database::get_manifest_certs(manifest_id { imp->get_oldstyle_certs(id.inner(), certs, "manifest_certs"); erase_bogus_certs_internal(certs, *this, - boost::bind(&lua_hooks::hook_get_manifest_cert_trust, - &this->lua, _1, _2, _3, _4)); + boost::bind(&check_manifest_cert_trust, + this, &this->lua, _1, _2, _3, _4)); } void @@ -3607,8 +3651,8 @@ database::get_manifest_certs(cert_name c { imp->get_oldstyle_certs(name, certs, "manifest_certs"); erase_bogus_certs_internal(certs, *this, - boost::bind(&lua_hooks::hook_get_manifest_cert_trust, - &this->lua, _1, _2, _3, _4)); + boost::bind(&check_manifest_cert_trust, + this, &this->lua, _1, _2, _3, _4)); } // completions ============================================================ --- database.hh fac63cd36816f326106c19fd56bd2e1b8246510c +++ database.hh e051b0dd5eca6894ae8bfc7a734d04f2ca7c7c52 @@ -27,6 +27,7 @@ class lazy_rng; class outdated_indicator; class rev_height; class lazy_rng; +class project_t; class migration_status; @@ -73,6 +74,7 @@ class database_impl; // the program. I don't know if there's any way to make it clearer. class database_impl; +struct key_identity_info; class database { @@ -313,7 +315,8 @@ public: id const &, cert_name const &, cert_value const &)> cert_trust_checker; - void erase_bogus_certs(std::vector & certs); + // this takes a project_t so it can translate key names for the trust hook + void erase_bogus_certs(project_t & project, std::vector & certs); // permit alternative trust functions void erase_bogus_certs(std::vector & certs, cert_trust_checker const & checker); ============================================================ --- key_store.cc 63bc362c154f9927410c87a2c1312cfe2c4520ca +++ key_store.cc cccb570b37409c34036e52f908a7246904d46337 @@ -19,6 +19,7 @@ #include "key_store.hh" #include "file_io.hh" #include "packet.hh" +#include "project.hh" #include "database.hh" #include "keys.hh" #include "globish.hh" @@ -485,7 +486,10 @@ key_store_state::decrypt_private_key(key utf8 phrase; string lua_phrase; // See whether a lua hook will tell us the passphrase. - if (!force_from_user && lua.hook_get_passphrase(name, id, lua_phrase)) + key_identity_info identity; + identity.id = id; + identity.given_name = name; + if (!force_from_user && lua.hook_get_passphrase(identity, lua_phrase)) phrase = utf8(lua_phrase, origin::user); else get_passphrase(phrase, name, id, false, false); @@ -887,8 +891,10 @@ key_store_state::migrate_old_key_pair shared_ptr priv_key; // See whether a lua hook will tell us the passphrase. + key_identity_info identity; + identity.given_name = id; string lua_phrase; - if (lua.hook_get_passphrase(id, key_id(), lua_phrase)) + if (lua.hook_get_passphrase(identity, lua_phrase)) phrase = utf8(lua_phrase, origin::user); else get_passphrase(phrase, id, key_id(), false, false); ============================================================ --- keys.cc c0a07b4c39c1ea1591d8694351659d3a4a5428bd +++ keys.cc f33f7007716e34467de1b15b300c268bf9762526 @@ -131,14 +131,9 @@ get_user_key(options const & opts, lua_h { if (!opts.signing_key().empty()) { - if (!opts.signing_key_id.inner()().empty()) - { - key = opts.signing_key_id; - } - else if (!opts.signing_key().empty()) - { - project.lookup_key_by_name(keys, opts.signing_key, key); - } + key_identity_info identity; + project.get_key_identity(keys, opts.signing_key, identity); + key = identity.id; } else { @@ -179,18 +174,16 @@ cache_netsync_key(options const & opts, // key_given is not set if the key option was extracted from the workspace if (opts.key_given || !opts.signing_key().empty()) { - if (!opts.signing_key_id.inner()().empty()) + key_identity_info identity; + // maybe they specifically requested no key ("--key ''") + if (!opts.signing_key().empty()) { - key = opts.signing_key_id; + project.get_key_identity(keys, opts.signing_key, identity); + key = identity.id; found_key = true; } - else if (!opts.signing_key().empty()) - { - project.lookup_key_by_name(keys, opts.signing_key, key); - found_key = true; - } } - else if (lua.hook_get_netsync_key(host, include, exclude, key)) + else if (lua.hook_get_netsync_key(host, include, exclude, keys, project, key)) { found_key = true; } ============================================================ --- lua_hooks.cc e5659dd576008ff3c863a27de3bcbda1bdad0186 +++ lua_hooks.cc 0a577a8ec34e3ccf46d9643bfd42a0fad63e3838 @@ -89,6 +89,21 @@ get_app_state(lua_State *LS) return NULL; } +namespace { + Lua & push_key_identity_info(Lua & ll, + key_identity_info const & info) + { + ll.push_table() + .push_str(info.id.inner()()) + .set_field("id") + .push_str(info.given_name()) + .set_field("given_name") + .push_str(info.official_name()) + .set_field("name"); + return ll; + } +} + lua_hooks::lua_hooks(app_state * app) { st = luaL_newstate(); @@ -230,17 +245,15 @@ bool // nb: if you're hooking lua to return your passphrase, you don't care if we // keep a couple extra temporaries of your passphrase around. bool -lua_hooks::hook_get_passphrase(key_name const & name, - key_id const & id, +lua_hooks::hook_get_passphrase(key_identity_info const & identity, string & phrase) { - return Lua(st) - .func("get_passphrase") - .push_str(name()) - .push_str(id.inner()()) - .call(2,1) - .extract_classified_str(phrase) - .ok(); + Lua ll(st); + ll.func("get_passphrase"); + push_key_identity_info(ll, identity); + ll.call(1,1) + .extract_classified_str(phrase); + return ll.ok(); } bool @@ -295,21 +308,22 @@ lua_hooks::hook_get_branch_key(branch_na .extract_str(key) .ok(); - key_name name(key, origin::user); - project.lookup_key_by_name(keys, name, k); + key_identity_info identity; + project.get_key_identity(keys, arg_type(key, origin::user), identity); + k = identity.id; return ok; } bool lua_hooks::hook_get_author(branch_name const & branchname, - key_id const & k, + key_identity_info const & identity, string & author) { - return Lua(st) - .func("get_author") - .push_str(branchname()) - .push_str(k.inner()()) - .call(2,1) + Lua ll(st); + ll.func("get_author") + .push_str(branchname()); + push_key_identity_info(ll, identity); + return ll.call(2,1) .extract_str(author) .ok(); } @@ -357,40 +371,59 @@ lua_hooks::hook_ignore_branch(branch_nam return exec_ok && ignore_it; } -static inline bool -shared_trust_function_body(Lua & ll, - set const & signers, - id const & hash, - cert_name const & name, - cert_value const & val) -{ - ll.push_table(); +namespace { + template + Lua & push_key_ident(Lua & ll, ID const & ident) + { + enum dummp { d = ( sizeof(struct not_a_key_id_type) == sizeof(ID))}; + return ll; + } + template<> + Lua & push_key_ident(Lua & ll, key_identity_info const & ident) + { + return push_key_identity_info(ll, ident); + } + template<> + Lua & push_key_ident(Lua & ll, key_name const & ident) + { + return ll.push_str(ident()); + } + template + bool + shared_trust_function_body(Lua & ll, + set const & signers, + id const & hash, + cert_name const & name, + cert_value const & val) + { + ll.push_table(); - int k = 1; - for (set::const_iterator v = signers.begin(); - v != signers.end(); ++v) - { - ll.push_int(k); - ll.push_str(v->inner()()); - ll.set_table(); - ++k; - } + int k = 1; + for (typename set::const_iterator v = signers.begin(); + v != signers.end(); ++v) + { + ll.push_int(k); + push_key_ident(ll, *v); + ll.set_table(); + ++k; + } - hexenc hid(encode_hexenc(hash(), hash.made_from), hash.made_from); - bool ok; - bool exec_ok = ll - .push_str(hid()) - .push_str(name()) - .push_str(val()) - .call(4, 1) - .extract_bool(ok) - .ok(); + hexenc hid(encode_hexenc(hash(), hash.made_from), hash.made_from); + bool ok; + bool exec_ok = ll + .push_str(hid()) + .push_str(name()) + .push_str(val()) + .call(4, 1) + .extract_bool(ok) + .ok(); - return exec_ok && ok; + return exec_ok && ok; + } } bool -lua_hooks::hook_get_revision_cert_trust(set const & signers, +lua_hooks::hook_get_revision_cert_trust(set const & signers, id const & hash, cert_name const & name, cert_value const & val) @@ -401,7 +434,7 @@ bool } bool -lua_hooks::hook_get_manifest_cert_trust(set const & signers, +lua_hooks::hook_get_manifest_cert_trust(set const & signers, id const & hash, cert_name const & name, cert_value const & val) @@ -619,6 +652,8 @@ lua_hooks::hook_get_netsync_key(utf8 con lua_hooks::hook_get_netsync_key(utf8 const & server_address, globish const & include, globish const & exclude, + key_store & keys, + project_t & project, key_id & k) { string name; @@ -634,8 +669,11 @@ lua_hooks::hook_get_netsync_key(utf8 con if (!exec_ok) name = ""; - // FIXME: translate - k = key_id(name, origin::user); + + key_identity_info identity; + project.get_key_identity(keys, arg_type(name, origin::user), identity); + k = identity.id; + return exec_ok; } @@ -762,15 +800,15 @@ lua_hooks::hook_get_netsync_read_permitt bool lua_hooks::hook_get_netsync_read_permitted(string const & branch, - key_id const & identity) + key_identity_info const & identity) { bool permitted = false, exec_ok = false; - exec_ok = Lua(st) - .func("get_netsync_read_permitted") - .push_str(branch) - .push_str(identity.inner()()) - .call(2,1) + Lua ll(st); + ll.func("get_netsync_read_permitted") + .push_str(branch); + push_key_identity_info(ll, identity); + exec_ok = ll.call(2,1) .extract_bool(permitted) .ok(); @@ -795,14 +833,14 @@ bool } bool -lua_hooks::hook_get_netsync_write_permitted(key_id const & identity) +lua_hooks::hook_get_netsync_write_permitted(key_identity_info const & identity) { bool permitted = false, exec_ok = false; - exec_ok = Lua(st) - .func("get_netsync_write_permitted") - .push_str(identity.inner()()) - .call(1,1) + Lua ll(st); + ll.func("get_netsync_write_permitted"); + push_key_identity_info(ll, identity); + exec_ok = ll.call(1,1) .extract_bool(permitted) .ok(); @@ -928,7 +966,7 @@ lua_hooks::hook_note_netsync_start(size_ bool lua_hooks::hook_note_netsync_start(size_t session_id, string my_role, int sync_type, string remote_host, - key_name remote_keyname, + key_identity_info const & remote_key, globish include_pattern, globish exclude_pattern) { @@ -949,14 +987,13 @@ lua_hooks::hook_note_netsync_start(size_ break; } Lua ll(st); - return ll - .func("note_netsync_start") + ll.func("note_netsync_start") .push_int(session_id) .push_str(my_role) .push_str(type) - .push_str(remote_host) - .push_str(remote_keyname()) - .push_str(include_pattern()) + .push_str(remote_host); + push_key_identity_info(ll, remote_key); + return ll.push_str(include_pattern()) .push_str(exclude_pattern()) .call(7, 0) .ok(); @@ -965,7 +1002,7 @@ lua_hooks::hook_note_netsync_revision_re bool lua_hooks::hook_note_netsync_revision_received(revision_id const & new_id, revision_data const & rdat, - set > > const & certs, size_t session_id) @@ -978,14 +1015,14 @@ lua_hooks::hook_note_netsync_revision_re ll.push_table(); - typedef set > > cdat; + typedef set > > cdat; int n = 1; for (cdat::const_iterator i = certs.begin(); i != certs.end(); ++i) { ll.push_int(n++); ll.push_table(); - ll.push_str(i->first.inner()()); + push_key_identity_info(ll, i->first); ll.set_field("key"); ll.push_str(i->second.first()); ll.set_field("name"); @@ -1002,7 +1039,7 @@ lua_hooks::hook_note_netsync_revision_se bool lua_hooks::hook_note_netsync_revision_sent(revision_id const & new_id, revision_data const & rdat, - set > > const & certs, size_t session_id) @@ -1015,14 +1052,14 @@ lua_hooks::hook_note_netsync_revision_se ll.push_table(); - typedef set > > cdat; + typedef set > > cdat; int n = 1; for (cdat::const_iterator i = certs.begin(); i != certs.end(); ++i) { ll.push_int(n++); ll.push_table(); - ll.push_str(i->first.inner()()); + push_key_identity_info(ll, i->first); ll.set_field("key"); ll.push_str(i->second.first()); ll.set_field("name"); @@ -1037,28 +1074,28 @@ bool } bool -lua_hooks::hook_note_netsync_pubkey_received(key_id const & kid, +lua_hooks::hook_note_netsync_pubkey_received(key_identity_info const & identity, size_t session_id) { Lua ll(st); ll - .func("note_netsync_pubkey_received") - .push_str(kid.inner()()) - .push_int(session_id); + .func("note_netsync_pubkey_received"); + push_key_identity_info(ll, identity); + ll.push_int(session_id); ll.call(2, 0); return ll.ok(); } bool -lua_hooks::hook_note_netsync_pubkey_sent(key_id const & kid, +lua_hooks::hook_note_netsync_pubkey_sent(key_identity_info const & identity, size_t session_id) { Lua ll(st); ll - .func("note_netsync_pubkey_sent") - .push_str(kid.inner()()) - .push_int(session_id); + .func("note_netsync_pubkey_sent"); + push_key_identity_info(ll, identity); + ll.push_int(session_id); ll.call(2, 0); return ll.ok(); @@ -1066,7 +1103,7 @@ lua_hooks::hook_note_netsync_cert_receiv bool lua_hooks::hook_note_netsync_cert_received(revision_id const & rid, - key_id const & kid, + key_identity_info const & identity, cert_name const & name, cert_value const & value, size_t session_id) @@ -1074,9 +1111,9 @@ lua_hooks::hook_note_netsync_cert_receiv Lua ll(st); ll .func("note_netsync_cert_received") - .push_str(encode_hexenc(rid.inner()(), rid.inner().made_from)) - .push_str(kid.inner()()) - .push_str(name()) + .push_str(encode_hexenc(rid.inner()(), rid.inner().made_from)); + push_key_identity_info(ll, identity); + ll.push_str(name()) .push_str(value()) .push_int(session_id); @@ -1086,17 +1123,17 @@ lua_hooks::hook_note_netsync_cert_sent(r bool lua_hooks::hook_note_netsync_cert_sent(revision_id const & rid, - key_id const & kid, - cert_name const & name, - cert_value const & value, - size_t session_id) + key_identity_info const & identity, + cert_name const & name, + cert_value const & value, + size_t session_id) { Lua ll(st); ll .func("note_netsync_cert_sent") - .push_str(encode_hexenc(rid.inner()(), rid.inner().made_from)) - .push_str(kid.inner()()) - .push_str(name()) + .push_str(encode_hexenc(rid.inner()(), rid.inner().made_from)); + push_key_identity_info(ll, identity); + ll.push_str(name()) .push_str(value()) .push_int(session_id); ============================================================ --- lua_hooks.hh 1d3b092d2abe0ab21fb41c5ccc22417cd5c7e6d0 +++ lua_hooks.hh 11905d6000abba47120174668fe2b28aa2608b2b @@ -29,6 +29,7 @@ class project_t; struct globish; struct options; class project_t; +struct key_identity_info; extern app_state* get_app_state(lua_State *LS); @@ -53,21 +54,20 @@ public: bool hook_get_branch_key(branch_name const & branchname, key_store & keys, project_t & project, key_id & k); - bool hook_get_passphrase(key_name const & name, - key_id const & id, + bool hook_get_passphrase(key_identity_info const & info, std::string & phrase); bool hook_get_author(branch_name const & branchname, - key_id const & k, + key_identity_info const & info, std::string & author); bool hook_edit_comment(external const & commentary, external const & user_log_message, external & result); bool hook_persist_phrase_ok(); - bool hook_get_revision_cert_trust(std::set const & signers, + bool hook_get_revision_cert_trust(std::set const & signers, id const & hash, cert_name const & name, cert_value const & val); - bool hook_get_manifest_cert_trust(std::set const & signers, + bool hook_get_manifest_cert_trust(std::set const & signers, id const & hash, cert_name const & name, cert_value const & val); @@ -78,6 +78,8 @@ public: bool hook_get_netsync_key(utf8 const & server_address, globish const & include, globish const & exclude, + key_store & keys, + project_t & project, key_id & k); bool hook_get_netsync_connect_command(uri const & u, globish const & include_pattern, @@ -87,10 +89,10 @@ public: bool hook_use_transport_auth(uri const & u); bool hook_get_netsync_read_permitted(std::string const & branch, - key_id const & identity); + key_identity_info const & identity); // anonymous no-key version bool hook_get_netsync_read_permitted(std::string const & branch); - bool hook_get_netsync_write_permitted(key_id const & identity); + bool hook_get_netsync_write_permitted(key_identity_info const & identity); // local repo hooks bool hook_ignore_file(file_path const & p); @@ -154,32 +156,32 @@ public: std::string my_role, int sync_type, std::string remote_host, - key_name remote_keyname, + key_identity_info const & remote_key, globish include_pattern, globish exclude_pattern); bool hook_note_netsync_revision_received(revision_id const & new_id, revision_data const & rdat, - std::set > > const & certs, size_t session_id); bool hook_note_netsync_revision_sent(revision_id const & new_id, revision_data const & rdat, - std::set > > const & certs, size_t session_id); - bool hook_note_netsync_pubkey_received(key_id const & kid, + bool hook_note_netsync_pubkey_received(key_identity_info const & identity, size_t session_id); - bool hook_note_netsync_pubkey_sent(key_id const & kid, + bool hook_note_netsync_pubkey_sent(key_identity_info const & identity, size_t session_id); bool hook_note_netsync_cert_received(revision_id const & rid, - key_id const & kid, + key_identity_info const & identity, cert_name const & name, cert_value const & value, size_t session_id); bool hook_note_netsync_cert_sent(revision_id const & rid, - key_id const & kid, + key_identity_info const & identity, cert_name const & name, cert_value const & value, size_t session_id); ============================================================ --- migrate_ancestry.cc bee80cc0f2ac2e39fba08bfbf759717665cdbe7f +++ migrate_ancestry.cc 60a55508a8a2e7dcbcea9f22ad19b8e1a0f8885c @@ -123,10 +123,12 @@ struct anc_graph struct anc_graph { - anc_graph(bool existing, database & db, key_store & keys) : + anc_graph(bool existing, database & db, key_store & keys, + project_t & project) : existing_graph(existing), db(db), keys(keys), + project(project), max_node(0), n_nodes("nodes", "n", 1), n_certs_in("certs in", "c", 1), @@ -137,6 +139,7 @@ struct anc_graph bool existing_graph; database & db; key_store & keys; + project_t & project; u64 max_node; ticker n_nodes; @@ -212,7 +215,6 @@ void anc_graph::write_certs() typedef multimap >::const_iterator ci; - project_t project(db); for (map::const_iterator i = node_to_new_rev.begin(); i != node_to_new_rev.end(); ++i) @@ -387,7 +389,7 @@ u64 anc_graph::add_node_for_oldstyle_rev // load certs vector rcerts; db.get_revision_certs(rev, rcerts); - db.erase_bogus_certs(rcerts); + db.erase_bogus_certs(project, rcerts); for(vector::const_iterator i = rcerts.begin(); i != rcerts.end(); ++i) { @@ -892,9 +894,10 @@ build_roster_style_revs_from_manifest_st void build_roster_style_revs_from_manifest_style_revs(database & db, key_store & keys, + project_t & project, set const & attrs_to_drop) { - anc_graph graph(true, db, keys); + anc_graph graph(true, db, keys, project); P(F("converting existing revision graph to new roster-style revisions")); multimap existing_graph; @@ -937,9 +940,10 @@ build_changesets_from_manifest_ancestry( void build_changesets_from_manifest_ancestry(database & db, key_store & keys, + project_t & project, set const & attrs_to_drop) { - anc_graph graph(false, db, keys); + anc_graph graph(false, db, keys, project); P(F("rebuilding revision graph from manifest certs")); ============================================================ --- migration.hh eddb224da22ddb812472fde688ca4ae8ce21bbeb +++ migration.hh 3dad1bb7ccc5d4cca2941b8a650770febeada6e0 @@ -22,6 +22,7 @@ class database; struct sqlite3; class key_store; class database; +class project_t; class system_path; std::string describe_sql_schema(sqlite3 * db); @@ -68,10 +69,12 @@ build_changesets_from_manifest_ancestry( void build_changesets_from_manifest_ancestry(database & db, key_store & keys, + project_t & project, std::set const & attrs_to_drop); void build_roster_style_revs_from_manifest_style_revs(database & db, key_store & keys, + project_t & project, std::set const & attrs_to_drop); void ============================================================ --- netsync.cc 632825f399ff0e1ef520b38fb8b2730606a20735 +++ netsync.cc fdc4cfa42234b01adfc25b5c4f57d603da54faf7 @@ -885,12 +885,12 @@ session::session(options & opts, rev_enumerator(project, *this), initiated_by_server(initiated_by_server) { - for (vector::const_iterator i = opts.keys_to_push.begin(); + for (vector::const_iterator i = opts.keys_to_push.begin(); i != opts.keys_to_push.end(); ++i) { - key_id ident; - project.lookup_key_by_name(keys, *i, ident); - keys_to_push.push_back(ident); + key_identity_info ident; + project.get_key_identity(keys, *i, ident); + keys_to_push.push_back(ident.id); } } @@ -929,7 +929,10 @@ session::~session() for (vector::iterator i = written_keys.begin(); i != written_keys.end(); ++i) { - lua.hook_note_netsync_pubkey_received(*i, session_id); + key_identity_info identity; + identity.id = *i; + project.complete_key_identity(keys, identity); + lua.hook_note_netsync_pubkey_received(identity, session_id); } //Revisions @@ -937,10 +940,15 @@ session::~session() i != written_revisions.end(); ++i) { vector & ctmp(rev_written_certs[*i]); - set > > certs; + set > > certs; for (vector::const_iterator j = ctmp.begin(); j != ctmp.end(); ++j) - certs.insert(make_pair(j->key, make_pair(j->name, j->value))); + { + key_identity_info identity; + identity.id = j->key; + project.complete_key_identity(keys, identity); + certs.insert(make_pair(identity, make_pair(j->name, j->value))); + } revision_data rdat; project.db.get_revision(*i, rdat); @@ -951,8 +959,13 @@ session::~session() //Certs (not attached to a new revision) for (vector::iterator i = unattached_written_certs.begin(); i != unattached_written_certs.end(); ++i) - lua.hook_note_netsync_cert_received(revision_id(i->ident), i->key, - i->name, i->value, session_id); + { + key_identity_info identity; + identity.id = i->key; + project.complete_key_identity(keys, identity); + lua.hook_note_netsync_cert_received(revision_id(i->ident), identity, + i->name, i->value, session_id); + } } if (!sent_keys.empty() @@ -980,7 +993,10 @@ session::~session() for (vector::iterator i = sent_keys.begin(); i != sent_keys.end(); ++i) { - lua.hook_note_netsync_pubkey_sent(*i, session_id); + key_identity_info identity; + identity.id = *i; + project.complete_key_identity(keys, identity); + lua.hook_note_netsync_pubkey_sent(identity, session_id); } //Revisions @@ -988,10 +1004,15 @@ session::~session() i != sent_revisions.end(); ++i) { vector & ctmp(rev_sent_certs[*i]); - set > > certs; + set > > certs; for (vector::const_iterator j = ctmp.begin(); j != ctmp.end(); ++j) - certs.insert(make_pair(j->key, make_pair(j->name, j->value))); + { + key_identity_info identity; + identity.id = j->key; + project.complete_key_identity(keys, identity); + certs.insert(make_pair(identity, make_pair(j->name, j->value))); + } revision_data rdat; project.db.get_revision(*i, rdat); @@ -1002,8 +1023,13 @@ session::~session() //Certs (not attached to a new revision) for (vector::iterator i = unattached_sent_certs.begin(); i != unattached_sent_certs.end(); ++i) - lua.hook_note_netsync_cert_sent(revision_id(i->ident), i->key, - i->name, i->value, session_id); + { + key_identity_info identity; + identity.id = i->key; + project.complete_key_identity(keys, identity); + lua.hook_note_netsync_cert_sent(revision_id(i->ident), identity, + i->name, i->value, session_id); + } } lua.hook_note_netsync_end(session_id, error_code, @@ -1591,14 +1617,14 @@ session::process_hello_cmd(key_name cons I(!this->received_remote_key); I(this->saved_nonce().empty()); + key_identity_info their_identity; if (use_transport_auth) { - key_id their_key_hash; - key_hash_code(their_keyname, their_key, their_key_hash); + key_hash_code(their_keyname, their_key, their_identity.id); var_value printable_key_hash; { hexenc encoded_key_hash; - encode_hexenc(their_key_hash.inner(), encoded_key_hash); + encode_hexenc(their_identity.id.inner(), encoded_key_hash); printable_key_hash = typecast_vocab(encoded_key_hash); } L(FL("server key has name %s, hash %s") @@ -1635,7 +1661,7 @@ session::process_hello_cmd(key_name cons project.db.set_var(their_key_key, printable_key_hash); } - if (!project.db.public_key_exists(their_key_hash)) + if (!project.db.public_key_exists(their_identity.id)) { // this should now always return true since we just checked // for the existence of this particular key @@ -1650,11 +1676,12 @@ session::process_hello_cmd(key_name cons % printable_key_hash % hnonce); } - I(project.db.public_key_exists(their_key_hash)); + I(project.db.public_key_exists(their_identity.id)); + project.complete_key_identity(keys, their_identity); // save their identity this->received_remote_key = true; - this->remote_peer_key_id = their_key_hash; + this->remote_peer_key_id = their_identity.id; } // clients always include in the synchronization set, every branch that the @@ -1693,7 +1720,7 @@ session::process_hello_cmd(key_name cons } lua.hook_note_netsync_start(session_id, "client", this->role, - peer_id, their_keyname, + peer_id, their_identity, our_include_pattern, our_exclude_pattern); return true; } @@ -1716,7 +1743,7 @@ session::process_anonymous_cmd(protocol_ // lua.hook_note_netsync_start(session_id, "server", their_role, - peer_id, key_name(), + peer_id, key_identity_info(), their_include_pattern, their_exclude_pattern); // Client must be a sink and server must be a source (anonymous @@ -1848,9 +1875,12 @@ session::process_auth_cmd(protocol_role key_name their_id; rsa_pub_key their_key; project.db.get_pubkey(client, their_id, their_key); + key_identity_info client_identity; + client_identity.id = client; + project.complete_key_identity(keys, client_identity); lua.hook_note_netsync_start(session_id, "server", their_role, - peer_id, their_id, + peer_id, client_identity, their_include_pattern, their_exclude_pattern); // Check that they replied with the nonce we asked for. @@ -1892,7 +1922,7 @@ session::process_auth_cmd(protocol_role { if (their_matcher((*i)())) { - if (!lua.hook_get_netsync_read_permitted((*i)(), client)) + if (!lua.hook_get_netsync_read_permitted((*i)(), client_identity)) { error(not_permitted, (F("denied '%s' read permission for '%s' excluding '%s' because of branch '%s'") @@ -1920,7 +1950,7 @@ session::process_auth_cmd(protocol_role % their_id % their_include_pattern % their_exclude_pattern).str()); } - if (!lua.hook_get_netsync_write_permitted(client)) + if (!lua.hook_get_netsync_write_permitted(client_identity)) { this->saved_nonce = id(""); error(not_permitted, ============================================================ --- options_list.hh 8a6808b055bed17d11f2c61924df3b73353f6a80 +++ options_list.hh dea0f08761112a3113a14a9f903b66faad4f02eb @@ -395,20 +395,11 @@ GOPT(ignore_suspend_certs, "ignore-suspe #endif -OPTVAR(key, key_name, signing_key, ) -OPTVAR(key, key_id, signing_key_id, ) +OPTVAR(key, arg_type, signing_key, ) OPTION(globals, key, true, "key,k", gettext_noop("set key for signatures")) #ifdef option_bodies { - internalize_key_name(utf8(arg, origin::user), signing_key); - try - { - signing_key_id = key_id(arg, origin::user); - } - catch(recoverable_failure &) - { - // not a valid ID, will have to be looked up later - } + signing_key = arg_type(arg, origin::user); } #endif @@ -423,14 +414,12 @@ OPTION(globals, key_dir, true, "keydir", } #endif -OPTVAR(key_to_push, std::vector, keys_to_push, ) +OPTVAR(key_to_push, std::vector, keys_to_push, ) OPTION(key_to_push, key_to_push, true, "key-to-push", gettext_noop("push the specified key even if it hasn't signed anything")) #ifdef option_bodies { - key_name keyid; - internalize_key_name(utf8(arg, origin::user), keyid); - keys_to_push.push_back(keyid); + keys_to_push.push_back(arg_type(arg, origin::user)); } #endif ============================================================ --- project.cc ead04f0d92d9364504b2a8cb93801c8a17a5984a +++ project.cc 3cf74cf70e55f430c08a27bc46c524ecd1b30e15 @@ -31,6 +31,31 @@ using boost::lexical_cast; using std::vector; using boost::lexical_cast; +bool +operator<(key_identity_info const & left, + key_identity_info const & right) +{ + if (left.id < right.id) + return true; + else if (left.id != right.id) + return false; + else if (left.official_name < right.official_name) + return true; + else if (left.official_name != right.official_name) + return false; + else + return left.given_name < right.given_name; +} +std::ostream & +operator<<(std::ostream & os, + key_identity_info const & identity) +{ + os<<"{id="< certs; - db.get_revision_certs(rid, - cert_name(branch_cert_name), - typecast_vocab(branch), - certs); - db.erase_bogus_certs(certs); + project.db.get_revision_certs(rid, + cert_name(branch_cert_name), + typecast_vocab(branch), + certs); + project.db.erase_bogus_certs(project, certs); return certs.empty(); } }; struct suspended_in_branch : public is_failure { - database & db; + project_t & project; branch_name const & branch; - suspended_in_branch(database & db, + suspended_in_branch(project_t & project, branch_name const & branch) - : db(db), branch(branch) + : project(project), branch(branch) {} virtual bool operator()(revision_id const & rid) { vector certs; - db.get_revision_certs(rid, - cert_name(suspend_cert_name), - typecast_vocab(branch), - certs); - db.erase_bogus_certs(certs); + project.db.get_revision_certs(rid, + cert_name(suspend_cert_name), + typecast_vocab(branch), + certs); + project.db.erase_bogus_certs(project, certs); return !certs.empty(); } }; @@ -150,13 +175,13 @@ project_t::get_branch_heads(branch_name typecast_vocab(name), branch.second); - not_in_branch p(db, name); + not_in_branch p(*this, name); erase_ancestors_and_failures(db, branch.second, p, inverse_graph_cache_ptr); if (!ignore_suspend_certs) { - suspended_in_branch s(db, name); + suspended_in_branch s(*this, name); set::iterator it = branch.second.begin(); while (it != branch.second.end()) if (s(*it)) @@ -181,7 +206,7 @@ project_t::revision_is_in_branch(revisio int num = certs.size(); - db.erase_bogus_certs(certs); + db.erase_bogus_certs(*this, certs); L(FL("found %d (%d valid) %s branch certs on revision %s") % num @@ -210,7 +235,7 @@ project_t::revision_is_suspended_in_bran int num = certs.size(); - db.erase_bogus_certs(certs); + db.erase_bogus_certs(*this, certs); L(FL("found %d (%d valid) %s suspend certs on revision %s") % num @@ -250,7 +275,7 @@ project_t::get_revision_certs_by_name(re vector & certs) { outdated_indicator i = db.get_revision_certs(id, name, certs); - db.erase_bogus_certs(certs); + db.erase_bogus_certs(*this, certs); return i; } @@ -305,7 +330,7 @@ project_t::get_tags(set & tags) { vector certs; outdated_indicator i = db.get_revision_certs(tag_cert_name, certs); - db.erase_bogus_certs(certs); + db.erase_bogus_certs(*this, certs); tags.clear(); for (vector::const_iterator i = certs.begin(); i != certs.end(); ++i) @@ -366,14 +391,13 @@ project_t::put_standard_certs_from_optio string author = opts.author(); if (author.empty()) { - key_id key; - get_user_key(opts, lua, db, keys, *this, key); + key_identity_info key; + get_user_key(opts, lua, db, keys, *this, key.id); + complete_key_identity(key); if (!lua.hook_get_author(branch, key, author)) { - key_name name; - get_name_of_key(keys, key, name); - author = name(); + author = key.official_name(); } } @@ -433,7 +457,7 @@ void } void -project_t::lookup_key_by_name(key_store & keys, +project_t::lookup_key_by_name(key_store * const keys, key_name const & name, key_id & id) { @@ -448,17 +472,20 @@ project_t::lookup_key_by_name(key_store set found; - vector storekeys; - keys.get_key_ids(storekeys); - for (vector::const_iterator i = storekeys.begin(); - i != storekeys.end(); ++i) + if (keys) { - key_name i_name; - keypair kp; - keys.get_key_pair(*i, i_name, kp); - if (i_name == name) + vector storekeys; + keys->get_key_ids(storekeys); + for (vector::const_iterator i = storekeys.begin(); + i != storekeys.end(); ++i) { - found.insert(*i); + key_name i_name; + keypair kp; + keys->get_key_pair(*i, i_name, kp); + if (i_name == name) + { + found.insert(*i); + } } } @@ -487,7 +514,7 @@ void } void -project_t::get_name_of_key(key_store & keys, +project_t::get_name_of_key(key_store * const keys, key_id const & id, key_name & name) { @@ -497,16 +524,16 @@ void } void -project_t::get_canonical_name_of_key(key_store & keys, +project_t::get_canonical_name_of_key(key_store * const keys, key_id const & id, key_name & name) { - if (keys.key_pair_exists(id)) + if (keys && keys->key_pair_exists(id)) { keypair kp; - keys.get_key_pair(id, name, kp); + keys->get_key_pair(id, name, kp); } - else if (db.public_key_exists(id)) + else if (db.database_specified() && db.public_key_exists(id)) { rsa_pub_key pub; db.get_pubkey(id, name, pub); @@ -518,6 +545,87 @@ project_t::get_canonical_name_of_key(key } } +void +project_t::complete_key_identity(key_store * const keys, + key_identity_info & info) +{ + if (!info.id.inner()().empty()) + { + get_name_of_key(keys, info.id, info.official_name); + get_canonical_name_of_key(keys, info.id, info.given_name); + } + else if (!info.official_name().empty()) + { + lookup_key_by_name(keys, info.official_name, info.id); + get_canonical_name_of_key(keys, info.id, info.given_name); + } + else if (!info.given_name().empty()) + { + lookup_key_by_name(keys, info.given_name, info.id); + get_name_of_key(keys, info.id, info.official_name); + } + else + I(false); +} + +void +project_t::complete_key_identity(key_store & keys, + key_identity_info & info) +{ + complete_key_identity(&keys, info); +} + +void +project_t::complete_key_identity(key_identity_info & info) +{ + complete_key_identity(0, info); +} + +void +project_t::get_key_identity(key_store * const keys, + arg_type const & input, + key_identity_info & output) +{ + try + { + string in = input(); + id ident; + try + { + string in2 = decode_hexenc(in, origin::no_fault); + ident = id(in2, origin::no_fault); + } + catch (recoverable_failure &) + { + ident = id(in, origin::no_fault); + } + // set this separately so we can ensure that the key_id() calls + // above throw recoverable_failure instead of unrecoverable_failure + ident.made_from = input.made_from; + output.id = key_id(ident); + } + catch (recoverable_failure &) + { + output.official_name = typecast_vocab(input); + } + complete_key_identity(keys, output); +} + +void +project_t::get_key_identity(key_store & keys, + arg_type const & input, + key_identity_info & output) +{ + get_key_identity(&keys, input, output); +} + +void +project_t::get_key_identity(arg_type const & input, + key_identity_info & output) +{ + get_key_identity(0, input, output); +} + // These should maybe be converted to member functions. string ============================================================ --- project.hh 0f53d807f622042c42a122866919c755bf8b3b2a +++ project.hh 3bc274753337aca0aa14d1fbb8320abd923fda04 @@ -17,6 +17,7 @@ #include "outdated_indicator.hh" #include "vocab.hh" +class arg_type; class database; class key_store; class options; @@ -42,6 +43,19 @@ struct date_t; #define comment_cert_name cert_name("comment") #define testresult_cert_name cert_name("testresult") +struct key_identity_info +{ + key_id id; + key_name given_name; // name given when creating the key + key_name official_name; // name returned by hooks or (once implented) policy +}; +bool +operator<(key_identity_info const & left, + key_identity_info const & right); +std::ostream & +operator<<(std::ostream & os, + key_identity_info const & identity); + class tag_t { public: @@ -134,18 +148,33 @@ public: revision_id const & id, utf8 const & comment); +private: // lookup the key ID associated with a particular key name - void lookup_key_by_name(key_store & keys, + void lookup_key_by_name(key_store * const keys, key_name const & name, key_id & id); // the reverse - void get_name_of_key(key_store & keys, + void get_name_of_key(key_store * const keys, key_id const & id, key_name & name); // get the name given when creating the key - void get_canonical_name_of_key(key_store & keys, + void get_canonical_name_of_key(key_store * const keys, key_id const & id, key_name & name); + void complete_key_identity(key_store * const keys, + key_identity_info & info); + void get_key_identity(key_store * const keys, + arg_type const & input, + key_identity_info & output); +public: + void complete_key_identity(key_store & keys, + key_identity_info & info); + void complete_key_identity(key_identity_info & info); + void get_key_identity(key_store & keys, + arg_type const & input, + key_identity_info & output); + void get_key_identity(arg_type const & input, + key_identity_info & output); }; std::string ============================================================ --- std_hooks.lua c9dd3ea46238ea2899e6d450154bca73f971547b +++ std_hooks.lua b0441ca2a69efe33d7df879dabd52019bb2bf42f @@ -1079,13 +1079,15 @@ function get_netsync_read_permitted(bran for j, val in pairs(item.values) do if val == "*" then return true end if val == "" and ident == nil then return true end - if globish_match(val, ident) then return true end + if val == ident.id then return true end + if globish_match(val, ident.name) then return true end end end elseif item.name == "deny" then if matches then for j, val in pairs(item.values) do if val == "*" then return false end if val == "" and ident == nil then return false end - if globish_match(val, ident) then return false end + if val == ident.id then return false end + if globish_match(val, ident.name) then return false end end end elseif item.name == "continue" then if matches then cont = true @@ -1110,7 +1112,8 @@ function get_netsync_write_permitted(ide while (not matches and line ~= nil) do local _, _, ln = string.find(line, "%s*([^%s]*)%s*") if ln == "*" then matches = true end - if globish_match(ln, ident) then matches = true end + if ln == ident.id then matches = true end + if globish_match(ln, ident.name) then matches = true end line = permfile:read() end io.close(permfile) ============================================================ --- tests/test_hooks.lua 33fa5ede0f6a84f7b4d8c2432a45e135ac5af936 +++ tests/test_hooks.lua d8e009b5e2c7d00afe4b301d60b8242936d6b794 @@ -12,7 +12,7 @@ function get_passphrase(keyid) -- production. just defines some of the std hooks. function get_passphrase(keyid) - return keyid + return keyid.given_name end -- Everything alice signs is trusted, nothing mallory signs is @@ -21,8 +21,8 @@ function get_revision_cert_trust(signers -- For use of t_trusted.at. function get_revision_cert_trust(signers, id, name, val) for k, v in pairs(signers) do - if v == "address@hidden" then return true end - if v == "address@hidden" then return false end + if v.given_name == "address@hidden" then return true end + if v.given_name == "address@hidden" then return false end end if (id == "0000000000000000000000000000000000000000" and name == "bad-cert" and val == "bad-val") @@ -106,4 +106,4 @@ do return argv; end -end \ No newline at end of file +end ============================================================ --- work.cc 925e839ec6e1ced6f9345dece76ee2d02a6fd526 +++ work.cc 9053a57ad3260c1c6f54e3b8aa038006b71e0119 @@ -400,7 +400,7 @@ read_options_file(any_path const & optsp read_options_file(any_path const & optspath, system_path & workspace_database, branch_name & workspace_branch, - key_name & workspace_key, + arg_type & workspace_key, system_path & workspace_keydir) { data dat; @@ -429,7 +429,7 @@ read_options_file(any_path const & optsp else if (opt == "branch") workspace_branch = branch_name(val, origin::workspace); else if (opt == "key") - internalize_key_name(utf8(val, origin::workspace), workspace_key); + workspace_key = arg_type(val, origin::workspace); else if (opt == "keydir") workspace_keydir = system_path(val, origin::workspace); else @@ -444,7 +444,7 @@ write_options_file(bookkeeping_path cons write_options_file(bookkeeping_path const & optspath, system_path const & workspace_database, branch_name const & workspace_branch, - key_name const & workspace_key, + arg_type const & workspace_key, system_path const & workspace_keydir) { basic_io::stanza st; @@ -454,9 +454,7 @@ write_options_file(bookkeeping_path cons st.push_str_pair(symbol("branch"), workspace_branch()); if (!workspace_key().empty()) { - utf8 key; - externalize_key_name(workspace_key, key); - st.push_str_pair(symbol("key"), key()); + st.push_str_pair(symbol("key"), workspace_key()); } if (!workspace_keydir.as_internal().empty()) st.push_str_pair(symbol("keydir"), workspace_keydir.as_internal()); @@ -481,7 +479,7 @@ workspace::get_options(options & opts) system_path workspace_database; branch_name workspace_branch; - key_name workspace_key; + arg_type workspace_key; system_path workspace_keydir; bookkeeping_path o_path; @@ -519,7 +517,7 @@ workspace::get_database_option(system_pa system_path & workspace_database) { branch_name workspace_branch; - key_name workspace_key; + arg_type workspace_key; system_path workspace_keydir; system_path o_path = (workspace @@ -542,7 +540,7 @@ workspace::set_options(options const & o // as is in _MTN/options, not write out an empty option. system_path workspace_database; branch_name workspace_branch; - key_name workspace_key; + arg_type workspace_key; system_path workspace_keydir; if (file_exists(o_path)) @@ -581,7 +579,7 @@ workspace::print_option(utf8 const & opt system_path workspace_database; branch_name workspace_branch; - key_name workspace_key; + arg_type workspace_key; system_path workspace_keydir; read_options_file(o_path, workspace_database, workspace_branch,