# # # patch "cert.cc" # from [0f86b8b9ce6559348a752649626bcaa6cf66d186] # to [9217fc9e7d471997b0761e4928bbf5eed0e220e0] # # patch "cert.hh" # from [f8ccd969215542f7a378381007368e5940c1ead3] # to [1e8a8efe49dbc5fce5b37d1f3d2a193299745337] # # patch "cmd_key_cert.cc" # from [2bd5467d5e63f2852a6a53be88e04e4f7ebc3f8a] # to [db863871951d61b405d1a8831835110660a2bf5f] # # patch "cmd_list.cc" # from [48c1e1bd67b5a41aa5dc47228fdd7b7523a96f2b] # to [81e8598541d0ab0f6fc77b3da679bff1eaa72ae7] # # patch "cmd_packet.cc" # from [7143d3fd50efc62b0ebb17d1ef894408ff5d6eeb] # to [cfeb4d5078c62d2e7f9db843fa01db6011d535f8] # # patch "constants.hh" # from [6dfe4845835786d6579cd86635f76096a30169ad] # to [adc7ef399cc939ee0b1ec47b97510f7ebdcaf2fd] # # patch "database.cc" # from [5b126ea1c1f3de12875b26ca4507a48fe7344c21] # to [d36a7cb2debc5ac21307fc66c441e90d9471dbbb] # # patch "database.hh" # from [87edc8755e0003a5f7d6fe62af6b09f61d04ae77] # to [350c0e0a3aee21669e46bf151a194ddec467052e] # # patch "key_store.cc" # from [04946f02ee5466f11c773f63c2073fb6294687e6] # to [31468d1502145cc28afe5982eec2fbc207aa5a74] # # patch "key_store.hh" # from [09d39f62751073603787ed802ae95c97dbe54ba6] # to [a6474bd1564c7658a85a839807e25c212b421fc3] # # patch "keys.cc" # from [6305335ead76e01e0415dfa625d4557b3467a5c4] # to [d7472aad14247172129668962aa73b019f812b33] # # patch "keys.hh" # from [36a7aea26b22ec80f48c24b68e7c356e21e3f213] # to [e34a1014fb262928b84c83c798081f6b24f10d7f] # # patch "lua_hooks.cc" # from [b681e7c7207510baa6eb9b33d4740d6122f18488] # to [79bfcd5bed4ab408686979288677fa6f92105048] # # patch "lua_hooks.hh" # from [07356795d81fbfd324c6261089386e28b77c1b75] # to [fe660f497db47dbd08c4324ab027ad54399b8e30] # # patch "migrate_ancestry.cc" # from [60ea5e154f134f633e1405cbd1d312d46a68464c] # to [20f631786b09b2c6c82effd5859813f175ce5e5f] # # patch "options_list.hh" # from [04514511db1d6d12e25f355816b21203822c89b2] # to [e401fd89ec9c48336dcd009a59424b8eb3b39b97] # # patch "project.cc" # from [f5ceff7a0415cb87e9870999585459b42c71e4df] # to [04cff64a5a395861e915b0787e453d8bc332dc2e] # # patch "project.hh" # from [e2f0f5db26a6d8bbe9214b264aca96b58513fcc8] # to [dee7f3ecb9b61646c3e8b296e38fa11d6081e763] # # patch "update.cc" # from [a67ae873fc4fca77ae07922e0b6869fc837ae550] # to [5f93a955ecd41f07490883ea0a76e01ec8cf7461] # ============================================================ --- cert.cc 0f86b8b9ce6559348a752649626bcaa6cf66d186 +++ cert.cc 9217fc9e7d471997b0761e4928bbf5eed0e220e0 @@ -63,7 +63,7 @@ read_cert(string const & in, cert & t) cert tmp(ident, cert_name(name, origin::network), cert_value(val, origin::network), - key_name(key, origin::network), + key_id(key, origin::network), rsa_sha1_signature(sig, origin::network)); id check; @@ -97,7 +97,7 @@ cert::marshal_for_netio(string & out) co out.append(this->ident.inner()()); insert_variable_length_string(this->name(), out); insert_variable_length_string(this->value(), out); - insert_variable_length_string(this->key(), out); + insert_variable_length_string(this->key.inner()(), out); insert_variable_length_string(this->sig(), out); } @@ -133,14 +133,14 @@ cert::hash_code(id & out) const string tmp; tmp.reserve(4 + ident_encoded.size() + this->name().size() + val_encoded().size() - + this->key().size() + sig_encoded().size()); + + this->key.inner()().size() + sig_encoded().size()); tmp.append(ident_encoded); tmp += ':'; tmp.append(this->name()); tmp += ':'; append_without_ws(tmp, val_encoded()); tmp += ':'; - tmp.append(this->key()); + tmp.append(this->key.inner()()); tmp += ':'; append_without_ws(tmp, sig_encoded()); ============================================================ --- cert.hh f8ccd969215542f7a378381007368e5940c1ead3 +++ cert.hh 1e8a8efe49dbc5fce5b37d1f3d2a193299745337 @@ -25,14 +25,14 @@ struct cert : public origin_aware cert(revision_id const & ident, cert_name const & name, cert_value const & value, - key_name const & key) + key_id const & key) : ident(ident), name(name), value(value), key(key) {} cert(revision_id const & ident, cert_name const & name, cert_value const & value, - key_name const & key, + key_id const & key, rsa_sha1_signature const & sig) : ident(ident), name(name), value(value), key(key), sig(sig) {} @@ -44,7 +44,7 @@ struct cert : public origin_aware revision_id ident; cert_name name; cert_value value; - key_name key; + key_id key; rsa_sha1_signature sig; bool operator<(cert const & other) const; ============================================================ --- cmd_key_cert.cc 2bd5467d5e63f2852a6a53be88e04e4f7ebc3f8a +++ cmd_key_cert.cc db863871951d61b405d1a8831835110660a2bf5f @@ -59,7 +59,10 @@ CMD(dropkey, "dropkey", "", CMD_REF(key_ if (args.size() != 1) throw usage(execid); - key_name ident = typecast_vocab(idx(args, 0)); + key_id ident; + project_t project(db); + project.lookup_key_by_name(typecast_vocab(idx(args, 0)), ident); + if (db.database_specified()) { transaction_guard guard(db); @@ -119,7 +122,7 @@ CMD(ssh_agent_export, "ssh_agent_export" if (args.size() > 1) throw usage(execid); - key_name id; + key_id id; get_user_key(app.opts, app.lua, db, keys, id); if (args.empty()) @@ -146,7 +149,7 @@ CMD(ssh_agent_add, "ssh_agent_add", "", if (args.size() > 1) throw usage(execid); - key_name id; + key_id id; get_user_key(app.opts, app.lua, db, keys, id); keys.add_key_to_agent(id); } @@ -213,12 +216,10 @@ 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) { - key_name keyid; - internalize_key_name(idx(args, i), keyid); - signers.insert(keyid); + signers.insert(decode_hexenc_as(idx(args, i)(), origin::user)); } @@ -229,7 +230,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 48c1e1bd67b5a41aa5dc47228fdd7b7523a96f2b +++ cmd_list.cc 81e8598541d0ab0f6fc77b3da679bff1eaa72ae7 @@ -77,7 +77,7 @@ CMD(certs, "certs", "", CMD_REF(list), " certs.push_back(idx(ts, i)); { - set checked; + set checked; for (size_t i = 0; i < certs.size(); ++i) { if (checked.find(idx(certs, i).key) == checked.end() && @@ -141,9 +141,9 @@ CMD(certs, "certs", "", CMD_REF(list), " cout << string(guess_terminal_width(), '-') << '\n' << (i18n_format(str) - % idx(certs, i).key() + % idx(certs, i).key % stat - % idx(certs, i).name() + % idx(certs, i).name % value_first_line); for (size_t i = 1; i < lines.size(); ++i) @@ -253,119 +253,180 @@ CMD(duplicates, "duplicates", "", CMD_RE } } +// hash => (given name, alias, public_location, private_location) +typedef boost::tuple, vector > key_info; +typedef map key_map; + +namespace { + void get_key_list(database & db, + key_store & keys, + project_t & project, + key_map & items) + { + items.clear(); + + { + vector dbkeys; + if (db.database_specified()) + { + db.get_key_ids(dbkeys); + 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(); + items[*i].get<2>().push_back("database"); + } + } + } + { + vector kskeys; + keys.get_key_ids(kskeys); + 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(); + items[*i].get<2>().push_back("keystore"); + items[*i].get<3>().push_back("keystore"); + } + } + } +} + CMD(keys, "keys", "", CMD_REF(list), "[PATTERN]", N_("Lists keys that match a pattern"), "", options::opts::none) { - database db(app); - key_store keys(app); - - vector pubs; - vector privkeys; - globish pattern("*", origin::internal); - if (args.size() == 1) - pattern = globish(idx(args, 0)(), origin::user); - else if (args.size() > 1) + if (args.size() > 1) throw usage(execid); - if (db.database_specified()) - db.get_key_ids(pattern, pubs); + database db(app); + key_store keys(app); + project_t project(db); - keys.get_key_ids(pattern, privkeys); + key_map items; + get_key_list(db, keys, project, items); - // true if it is in the database, false otherwise - map pubkeys; - for (vector::const_iterator i = pubs.begin(); - i != pubs.end(); i++) - pubkeys[*i] = true; + if (items.empty()) + { + P(F("no keys found")); + } - set bad_keys; - - bool all_in_db = true; - for (vector::const_iterator i = privkeys.begin(); - i != privkeys.end(); i++) + key_map matched_items; + if (args.size() == 1) { - if (pubkeys.find(*i) == pubkeys.end()) + globish pattern(idx(args, 0)(), origin::user); + for (key_map::iterator i = items.begin(); i != items.end(); ++i) { - pubkeys[*i] = false; - all_in_db = false; + string const & alias = i->second.get<1>(); + if (pattern.matches(alias)) + { + matched_items.insert(*i); + } } - else if (db.database_specified()) + if (matched_items.empty()) { - // we've found a key that should have both a public and a private version - rsa_pub_key pub_key; - keypair priv_key; - db.get_key(*i, pub_key); - keys.get_key_pair(*i, priv_key); - if (!keys_match(*i, pub_key, *i, priv_key.pub)) - bad_keys.insert(*i); + W(F("no keys found matching '%s'") % idx(args, 0)()); } } + else + { + matched_items = items; + } - if (!pubkeys.empty()) + bool have_keystore_only_key = false; + // sort key => rendered line + map public_rendered; + map private_rendered; + + set seen_aliases; + set duplicate_aliases; + + for (key_map::iterator i = matched_items.begin(); + i != matched_items.end(); ++i) { - cout << "\n[public keys]\n"; - for (map::iterator i = pubkeys.begin(); - i != pubkeys.end(); i++) + key_id const & id = i->first; + string const & given_name = i->second.get<0>(); + string const & alias = i->second.get<1>(); + vector const & public_locations = i->second.get<2>(); + vector const & private_locations = i->second.get<3>(); + + if (seen_aliases.find(alias) != seen_aliases.end()) { - rsa_pub_key pub_encoded; - id hash_code; - key_name keyid = i->first; - bool indb = i->second; + duplicate_aliases.insert(alias); + } + seen_aliases.insert(alias); - if (indb) - db.get_key(keyid, pub_encoded); - else + string rendered_basic = id.inner()() + string(" ") + alias; + if (given_name != alias) + { + rendered_basic += string(" (") + given_name + string(")"); + } + + if (!public_locations.empty()) + { + string rendered = rendered_basic; + if (public_locations.size() == 1 && + idx(public_locations, 0) == "keystore") { - keypair kp; - keys.get_key_pair(keyid, kp); - pub_encoded = kp.pub; + have_keystore_only_key = true; + rendered_basic += " (*)"; } - key_hash_code(keyid, pub_encoded, hash_code); - if (indb) - cout << hash_code << ' ' << keyid << '\n'; - else - cout << hash_code << ' ' << keyid << " (*)\n"; + public_rendered.insert(make_pair(alias, rendered)); } - if (!all_in_db) - cout << (F("(*) - only in %s/") - % keys.get_key_dir()) << '\n'; - cout << '\n'; + if (!private_locations.empty()) + { + private_rendered.insert(make_pair(alias, rendered_basic)); + } } - if (!privkeys.empty()) + if (!public_rendered.empty()) { + cout << "\n[public keys]\n"; + for (map::iterator i = public_rendered.begin(); + i != public_rendered.end(); ++i) + { + cout << i->second << "\n"; + } + if (have_keystore_only_key) + { + cout << (F("(*) - only in %s/") + % keys.get_key_dir()) << '\n'; + } + cout << "\n"; + } + if (!private_rendered.empty()) + { cout << "\n[private keys]\n"; - for (vector::iterator i = privkeys.begin(); - i != privkeys.end(); i++) + for (map::iterator i = private_rendered.begin(); + i != private_rendered.end(); ++i) { - keypair kp; - id hash_code; - keys.get_key_pair(*i, kp); - key_hash_code(*i, kp.pub, hash_code); - cout << hash_code << ' ' << *i << '\n'; + cout << i->second << "\n"; } - cout << '\n'; + cout << "\n"; } - if (!bad_keys.empty()) + if (!duplicate_aliases.empty()) { - W(F("Some keys in the database have the same ID as, " - "but different hashes to, keys in your local key store!")); - for (set::const_iterator i = bad_keys.begin(); i != bad_keys.end(); i++) + W(F("Some key names refer to multiple keys")); + for (set::iterator i = duplicate_aliases.begin(); + i != duplicate_aliases.end(); i++) { W(F("Mismatched Key: %s") % *i); } } - if (pubkeys.empty() && privkeys.empty()) - { - if (args.empty()) - P(F("no keys found")); - else - W(F("no keys found matching '%s'") % idx(args, 0)()); - } } CMD(branches, "branches", "", CMD_REF(list), "[PATTERN]", @@ -687,52 +748,21 @@ CMD_AUTOMATE(keys, "", database db(app); key_store keys(app); + project_t project(db); - vector dbkeys; - vector kskeys; - // hash, public_location, private_location - map, - vector > > items; - if (db.database_specified()) - db.get_key_ids(dbkeys); + key_map items; + get_key_list(db, keys, project, items); - keys.get_key_ids(kskeys); - - for (vector::iterator i = dbkeys.begin(); - i != dbkeys.end(); i++) - { - rsa_pub_key pub_encoded; - id hash_code; - db.get_key(*i, pub_encoded); - key_hash_code(*i, pub_encoded, hash_code); - items[(*i)()].get<0>() = hash_code; - items[(*i)()].get<1>().push_back("database"); - } - - for (vector::iterator i = kskeys.begin(); - i != kskeys.end(); i++) - { - keypair kp; - id privhash, pubhash; - keys.get_key_pair(*i, kp); - key_hash_code(*i, kp.pub, pubhash); - items[(*i)()].get<0>() = pubhash; - items[(*i)()].get<1>().push_back("keystore"); - items[(*i)()].get<2>().push_back("keystore"); - } basic_io::printer prt; - for (map, - vector > >::iterator - i = items.begin(); i != items.end(); ++i) + for (key_map::iterator i = items.begin(); i != items.end(); ++i) { basic_io::stanza stz; - stz.push_str_pair(syms::name, i->first); - stz.push_binary_pair(syms::hash, i->second.get<0>()); - stz.push_str_multi(syms::public_location, i->second.get<1>()); + stz.push_binary_pair(syms::hash, i->first.inner()); + stz.push_str_pair(syms::name, i->second.get<0>()); + stz.push_str_pair(syms::name, i->second.get<1>());/* FIXME */ + stz.push_str_multi(syms::public_location, i->second.get<2>()); if (!i->second.get<2>().empty()) - stz.push_str_multi(syms::private_location, i->second.get<2>()); + stz.push_str_multi(syms::private_location, i->second.get<3>()); prt.print_stanza(stz); } output.write(prt.buf.data(), prt.buf.size()); @@ -797,7 +827,7 @@ CMD_AUTOMATE(certs, N_("REV"), certs.push_back(idx(ts, i)); { - set checked; + set checked; for (size_t i = 0; i < certs.size(); ++i) { if (checked.find(idx(certs, i).key) == checked.end() && @@ -820,16 +850,16 @@ 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_name keyid = idx(certs, i).key; + key_id keyid = idx(certs, i).key; signers.insert(keyid); bool trusted = app.lua.hook_get_revision_cert_trust(signers, rid.inner(), name, tv); - st.push_str_pair(syms::key, keyid()); + st.push_str_pair(syms::key, keyid.inner()()); string stat; switch (status) ============================================================ --- cmd_packet.cc 7143d3fd50efc62b0ebb17d1ef894408ff5d6eeb +++ cmd_packet.cc cfeb4d5078c62d2e7f9db843fa01db6011d535f8 @@ -16,6 +16,7 @@ #include "database.hh" #include "key_store.hh" #include "packet.hh" +#include "project.hh" #include "vocab_cast.hh" using std::cin; @@ -34,7 +35,9 @@ CMD(pubkey, "pubkey", "", CMD_REF(packet if (args.size() != 1) throw usage(execid); - key_name ident = typecast_vocab(idx(args, 0)); + key_id ident; + project_t project(db); + project.lookup_key_by_name(typecast_vocab(idx(args, 0)), ident); bool exists(false); rsa_pub_key key; if (db.database_specified() && db.public_key_exists(ident)) ============================================================ --- constants.hh 6dfe4845835786d6579cd86635f76096a30169ad +++ constants.hh adc7ef399cc939ee0b1ec47b97510f7ebdcaf2fd @@ -128,7 +128,7 @@ namespace constants = merkle_bitmap_length_in_bits / 8; // the current netcmd/netsync protocol version - u8 const netcmd_current_protocol_version = 6; + u8 const netcmd_current_protocol_version = 7; // minimum size of any netcmd on the wire std::size_t const netcmd_minsz = (1 // version ============================================================ --- database.cc 5b126ea1c1f3de12875b26ca4507a48fe7344c21 +++ database.cc d36a7cb2debc5ac21307fc66c441e90d9471dbbb @@ -365,10 +365,16 @@ private: void put_cert(cert const & t, string const & table); void results_to_certs(results const & res, vector & certs); + void oldstyle_results_to_certs(results const & res, + vector & certs); void get_certs(vector & certs, string const & table); + void get_oldstyle_certs(id const & ident, + vector & certs, + string const & table); + void get_certs(id const & ident, vector & certs, string const & table); @@ -377,6 +383,10 @@ private: vector & certs, string const & table); + void get_oldstyle_certs(cert_name const & name, + vector & certs, + string const & table); + void get_certs(id const & ident, cert_name const & name, vector & certs, @@ -2979,12 +2989,12 @@ database::put_key(key_name const & pub_i L(FL("putting public key %s") % pub_id); - id thash; + key_id thash; key_hash_code(pub_id, pub, thash); I(!public_key_exists(thash)); imp->execute(query("INSERT INTO public_keys VALUES(?, ?, ?)") - % blob(thash()) + % blob(thash.inner()()) % text(pub_id()) % blob(pub())); @@ -3037,7 +3047,7 @@ cert_status } cert_status -database::check_signature(key_name const & id, +database::check_signature(key_id const & id, string const & alleged_text, rsa_sha1_signature const & signature) { @@ -3104,15 +3114,15 @@ database_impl::cert_exists(cert const & string const & table) { results res; - query q = query("SELECT id FROM " + table + " WHERE id = ? " + query q = query("SELECT revision_id FROM " + table + " WHERE revision_id = ? " "AND name = ? " "AND value = ? " - "AND keypair = ? " + "AND keypair_id = ? " "AND signature = ?") % blob(t.ident.inner()()) % text(t.name()) % blob(t.value()) - % text(t.key()) + % text(t.key.inner()()) % blob(t.sig()); fetch(res, 1, any_rows, q); @@ -3136,7 +3146,7 @@ database_impl::put_cert(cert const & t, % blob(t.ident.inner()()) % text(t.name()) % blob(t.value()) - % text(t.key()) + % text(t.key.inner()()) % blob(t.sig())); } @@ -3151,13 +3161,44 @@ database_impl::results_to_certs(results t = cert(revision_id(res[i][0], origin::database), cert_name(res[i][1], origin::database), cert_value(res[i][2], origin::database), - key_name(res[i][3], origin::database), + key_id(res[i][3], origin::database), rsa_sha1_signature(res[i][4], origin::database)); certs.push_back(t); } } void +database_impl::oldstyle_results_to_certs(results const & res, + vector & certs) +{ + certs.clear(); + for (size_t i = 0; i < res.size(); ++i) + { + revision_id rev_id(res[i][0], origin::database); + cert_name name(res[i][1], origin::database); + cert_value value(res[i][2], origin::database); + + key_name k_name(res[i][3], origin::database); + key_id k_id; + { + results key_res; + query lookup_key("SELECT id FROM public_keys WHERE name = ?"); + fetch(key_res, 1, any_rows, lookup_key % k_name); + if (key_res.size() == 0) + break; // no key, cert is bogus + else if (key_res.size() == 1) + k_id = key_id(key_res[0][0], origin::database); + else + E(false, origin::database, + F("Your database contains multiple keys named %s") % k_name); + } + + rsa_sha1_signature sig(res[i][4], origin::database); + certs.push_back(cert(rev_id, name, value, k_id, sig)); + } +} + +void database_impl::install_functions() { #ifdef SUPPORT_SQLITE_BEFORE_3003014 @@ -3180,38 +3221,61 @@ database_impl::get_certs(vector & string const & table) { results res; - query q("SELECT id, name, value, keypair, signature FROM " + table); + query q("SELECT revision_id, name, value, keypair_id, signature FROM " + table); fetch(res, 5, any_rows, q); results_to_certs(res, certs); } void +database_impl::get_oldstyle_certs(id const & ident, + vector & certs, + string const & table) +{ + results res; + query q("SELECT id, name, value, keypair, signature FROM " + table + + " WHERE id = ?"); + + fetch(res, 5, any_rows, q % blob(ident())); + oldstyle_results_to_certs(res, certs); +} + +void database_impl::get_certs(id const & ident, vector & certs, string const & table) { results res; - query q("SELECT id, name, value, keypair, signature FROM " + table + - " WHERE id = ?"); + query q("SELECT revision_id, name, value, keypair_id, signature FROM " + table + + " WHERE revision_id = ?"); fetch(res, 5, any_rows, q % blob(ident())); results_to_certs(res, certs); } - void database_impl::get_certs(cert_name const & name, vector & certs, string const & table) { results res; - query q("SELECT id, name, value, keypair, signature FROM " + table + + query q("SELECT revision_id, name, value, keypair_id, signature FROM " + table + " WHERE name = ?"); fetch(res, 5, any_rows, q % text(name())); results_to_certs(res, certs); } +void +database_impl::get_oldstyle_certs(cert_name const & name, + vector & certs, + string const & table) +{ + results res; + query q("SELECT id, name, value, keypair, signature FROM " + table + + " WHERE name = ?"); + fetch(res, 5, any_rows, q % text(name())); + oldstyle_results_to_certs(res, certs); +} void database_impl::get_certs(id const & ident, @@ -3220,8 +3284,8 @@ database_impl::get_certs(id const & iden string const & table) { results res; - query q("SELECT id, name, value, keypair, signature FROM " + table + - " WHERE id = ? AND name = ?"); + query q("SELECT revision_id, name, value, keypair_id, signature FROM " + table + + " WHERE revision_id = ? AND name = ?"); fetch(res, 5, any_rows, q % blob(ident()) @@ -3236,7 +3300,7 @@ database_impl::get_certs(cert_name const string const & table) { results res; - query q("SELECT id, name, value, keypair, signature FROM " + table + + query q("SELECT revision_id, name, value, keypair_id, signature FROM " + table + " WHERE name = ? AND value = ?"); fetch(res, 5, any_rows, @@ -3254,8 +3318,8 @@ database_impl::get_certs(id const & iden string const & table) { results res; - query q("SELECT id, name, value, keypair, signature FROM " + table + - " WHERE id = ? AND name = ? AND value = ?"); + query q("SELECT revision_id, name, value, keypair_id, signature FROM " + table + + " WHERE revision_id = ? AND name = ? AND value = ?"); fetch(res, 5, any_rows, q % blob(ident()) @@ -3384,6 +3448,14 @@ outdated_indicator } outdated_indicator +database::get_oldstyle_revision_certs(revision_id const & id, + vector & certs) +{ + imp->get_oldstyle_certs(id.inner(), certs, "revision_certs"); + return imp->cert_stamper.get_indicator(); +} + +outdated_indicator database::get_revision_certs(revision_id const & ident, vector & ids) { @@ -3450,7 +3522,7 @@ namespace { { string txt; c.signable_text(txt); - W(F("ignoring bad signature by '%s' on '%s'") % c.key() % txt); + W(F("ignoring bad signature by '%s' on '%s'") % c.key % txt); return true; } else @@ -3458,7 +3530,7 @@ namespace { I(status == cert_unknown); string txt; c.signable_text(txt); - W(F("ignoring unknown signature by '%s' on '%s'") % c.key() % txt); + W(F("ignoring unknown signature by '%s' on '%s'") % c.key % txt); return true; } } @@ -3478,7 +3550,7 @@ namespace { // sorry, this is a crazy data structure typedef tuple trust_key; typedef map< trust_key, - pair< shared_ptr< set >, it > > trust_map; + pair< shared_ptr< set >, it > > trust_map; trust_map trust; for (it i = certs.begin(); i != certs.end(); ++i) @@ -3487,10 +3559,10 @@ namespace { i->name, i->value); trust_map::iterator j = trust.find(key); - shared_ptr< set > s; + shared_ptr< set > s; if (j == trust.end()) { - s.reset(new set()); + s.reset(new set()); trust.insert(make_pair(key, make_pair(s, i))); } else @@ -3546,7 +3618,7 @@ database::get_manifest_certs(manifest_id void database::get_manifest_certs(manifest_id const & id, std::vector & certs) { - imp->get_certs(id.inner(), certs, "manifest_certs"); + 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)); @@ -3555,7 +3627,7 @@ database::get_manifest_certs(cert_name c void database::get_manifest_certs(cert_name const & name, std::vector & certs) { - imp->get_certs(name, certs, "manifest_certs"); + 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)); ============================================================ --- database.hh 87edc8755e0003a5f7d6fe62af6b09f61d04ae77 +++ database.hh 350c0e0a3aee21669e46bf151a194ddec467052e @@ -230,31 +230,29 @@ public: // --== Keys ==-- // public: - void get_key_ids(std::vector & pubkeys); - void get_key_ids(globish const & pattern, - std::vector & pubkeys); + void get_key_ids(std::vector & pubkeys); void get_public_keys(std::vector & pubkeys); - bool public_key_exists(id const & hash); + bool public_key_exists(key_id const & hash); bool public_key_exists(key_name const & ident); void get_pubkey(id const & hash, key_name & ident, rsa_pub_key & pub); - void get_key(key_name const & ident, rsa_pub_key & pub); + void get_key(key_id const & ident, rsa_pub_key & pub); bool put_key(key_name const & ident, rsa_pub_key const & pub); - void delete_public_key(key_name const & pub_id); + void delete_public_key(key_id const & pub_id); // Crypto operations - void encrypt_rsa(key_name const & pub_id, + void encrypt_rsa(key_id const & pub_id, std::string const & plaintext, rsa_oaep_sha_data & ciphertext); - cert_status check_signature(key_name const & id, + cert_status check_signature(key_id const & id, std::string const & alleged_text, rsa_sha1_signature const & signature); cert_status check_cert(cert const & t); @@ -299,18 +297,21 @@ public: cert_value const & value, std::set & revisions); - // Used through project.cc, and by - // anc_graph::add_node_for_oldstyle_revision (revision.cc) + // Used through project.cc outdated_indicator get_revision_certs(revision_id const & ident, std::vector & certs); + // used by anc_graph::add_node_for_oldstyle_revision (revision.cc) + outdated_indicator get_oldstyle_revision_certs(revision_id const & ident, + std::vector & certs); + // Used through get_revision_cert_hashes (project.cc) outdated_indicator get_revision_certs(revision_id const & ident, std::vector & hashes); void get_revision_cert(id const & hash, cert & c); - typedef boost::function const &, + typedef boost::function const &, id const &, cert_name const &, cert_value const &)> cert_trust_checker; ============================================================ --- key_store.cc 04946f02ee5466f11c773f63c2073fb6294687e6 +++ key_store.cc 31468d1502145cc28afe5982eec2fbc207aa5a74 @@ -253,7 +253,7 @@ bool } bool -key_store::key_pair_exists(key_name const & ident) +key_store::key_pair_exists(key_id const & ident) { s->maybe_read_key_dir(); return s->keys.find(ident) != s->keys.end(); @@ -379,7 +379,7 @@ void } void -key_store::delete_key(key_name const & ident) +key_store::delete_key(key_id const & ident) { s->maybe_read_key_dir(); map::iterator i = s->keys.find(ident); ============================================================ --- key_store.hh 09d39f62751073603787ed802ae95c97dbe54ba6 +++ key_store.hh a6474bd1564c7658a85a839807e25c212b421fc3 @@ -47,7 +47,7 @@ public: boost::scoped_ptr s; public: - key_name signing_key; + key_id signing_key; bool have_signing_key() const; explicit key_store(app_state & a); @@ -61,15 +61,13 @@ public: // Basic key I/O - void get_key_ids(std::vector & priv); - void get_key_ids(globish const & pattern, - std::vector & priv); + void get_key_ids(std::vector & priv); - bool key_pair_exists(key_name const & ident); + bool key_pair_exists(key_id const & ident); - void get_key_pair(key_name const & ident, + void get_key_pair(key_id const & ident, keypair & kp); - bool maybe_get_key_pair(key_name const & ident, + bool maybe_get_key_pair(key_id const & ident, keypair & kp); bool maybe_get_key_pair(id const & hash, key_name & ident, @@ -78,30 +76,30 @@ public: bool put_key_pair(key_name const & ident, keypair const & kp); - void delete_key(key_name const & ident); + void delete_key(key_id const & ident); // Crypto operations - void cache_decrypted_key(key_name const & id); + void cache_decrypted_key(key_id const & id); void create_key_pair(database & db, key_name const & ident, utf8 const * maybe_passphrase = NULL, id * maybe_hash = NULL); - void change_key_passphrase(key_name const & id); + void change_key_passphrase(key_id const & id); - void decrypt_rsa(key_name const & id, + void decrypt_rsa(key_id const & id, rsa_oaep_sha_data const & ciphertext, std::string & plaintext); - void make_signature(database & db, key_name const & id, + void make_signature(database & db, key_id const & id, std::string const & tosign, rsa_sha1_signature & signature); // Interoperation with ssh-agent - void add_key_to_agent(key_name const & id); - void export_key_for_agent(key_name const & id, + void add_key_to_agent(key_id const & id); + void export_key_for_agent(key_id const & id, std::ostream & os); // Migration from old databases ============================================================ --- keys.cc 6305335ead76e01e0415dfa625d4557b3467a5c4 +++ keys.cc d7472aad14247172129668962aa73b019f812b33 @@ -33,7 +33,7 @@ void // if that key pair is not available. void -load_key_pair(key_store & keys, key_name const & id) +load_key_pair(key_store & keys, key_id const & id) { E(keys.key_pair_exists(id), origin::user, F("no key pair '%s' found in key store '%s'") @@ -42,7 +42,7 @@ load_key_pair(key_store & keys, void load_key_pair(key_store & keys, - key_name const & id, + key_id const & id, keypair & kp) { load_key_pair(keys, id); @@ -105,7 +105,7 @@ get_user_key(options const & opts, lua_h void get_user_key(options const & opts, lua_hooks & lua, - database & db, key_store & keys, key_name & key) + database & db, key_store & keys, key_id & key) { if (keys.have_signing_key()) { @@ -186,6 +186,19 @@ void } void +get_netsync_key(options const & opts, lua_hooks & lua, + database & db, key_store & keys, + netsync_key_requiredness key_requiredness, + key_id & key) +{ + if (!keys.signing_key().empty()) + { + key = keys.signing_key; + return; + } +} + +void key_hash_code(key_name const & ident, rsa_pub_key const & pub, id & out) ============================================================ --- keys.hh 36a7aea26b22ec80f48c24b68e7c356e21e3f213 +++ keys.hh e34a1014fb262928b84c83c798081f6b24f10d7f @@ -29,7 +29,7 @@ void get_user_key(options const & opts, // form, so as not to bother the user for their passphrase later. void get_user_key(options const & opts, lua_hooks & lua, database & db, key_store & keys, - key_name & key); + key_id & key); // As above, but does not report which key has been selected; for use when // the important thing is to have selected one and cached the decrypted key. @@ -48,10 +48,10 @@ void load_key_pair(key_store & keys, netsync_key_requiredness key_requiredness); void load_key_pair(key_store & keys, - key_name const & id); + key_id const & id); void load_key_pair(key_store & keys, - key_name const & id, + key_id const & id, keypair & kp); // netsync stuff ============================================================ --- lua_hooks.cc b681e7c7207510baa6eb9b33d4740d6122f18488 +++ lua_hooks.cc 79bfcd5bed4ab408686979288677fa6f92105048 @@ -295,13 +295,13 @@ lua_hooks::hook_get_author(branch_name c bool lua_hooks::hook_get_author(branch_name const & branchname, - key_name const & k, + key_id const & k, string & author) { return Lua(st) .func("get_author") .push_str(branchname()) - .push_str(k()) + .push_str(k.inner()()) .call(2,1) .extract_str(author) .ok(); @@ -352,7 +352,7 @@ shared_trust_function_body(Lua & ll, static inline bool shared_trust_function_body(Lua & ll, - set const & signers, + set const & signers, id const & hash, cert_name const & name, cert_value const & val) @@ -360,11 +360,11 @@ shared_trust_function_body(Lua & ll, ll.push_table(); int k = 1; - for (set::const_iterator v = signers.begin(); + for (set::const_iterator v = signers.begin(); v != signers.end(); ++v) { ll.push_int(k); - ll.push_str((*v)()); + ll.push_str(v->inner()()); ll.set_table(); ++k; } @@ -383,7 +383,7 @@ bool } 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) @@ -394,7 +394,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) @@ -405,28 +405,28 @@ bool } bool -lua_hooks::hook_accept_testresult_change(map const & old_results, - map const & new_results) +lua_hooks::hook_accept_testresult_change(map const & old_results, + map const & new_results) { Lua ll(st); ll .func("accept_testresult_change") .push_table(); - for (map::const_iterator i = old_results.begin(); + for (map::const_iterator i = old_results.begin(); i != old_results.end(); ++i) { - ll.push_str(i->first()); + ll.push_str(i->first.inner()()); ll.push_bool(i->second); ll.set_table(); } ll.push_table(); - for (map::const_iterator i = new_results.begin(); + for (map::const_iterator i = new_results.begin(); i != new_results.end(); ++i) { - ll.push_str(i->first()); + ll.push_str(i->first.inner()()); ll.push_bool(i->second); ll.set_table(); } @@ -595,9 +595,9 @@ 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_name & k) + key_id & k) { - string key_id; + string name; bool exec_ok = Lua(st) .func("get_netsync_key") @@ -605,12 +605,13 @@ lua_hooks::hook_get_netsync_key(utf8 con .push_str(include()) .push_str(exclude()) .call(3, 1) - .extract_str(key_id) + .extract_str(name) .ok(); if (!exec_ok) - key_id = ""; - k = key_name(key_id, origin::user); + name = ""; + // FIXME: translate + k = key_id(name, origin::user); return exec_ok; } @@ -737,14 +738,14 @@ lua_hooks::hook_get_netsync_read_permitt bool lua_hooks::hook_get_netsync_read_permitted(string const & branch, - key_name const & identity) + key_id const & identity) { bool permitted = false, exec_ok = false; exec_ok = Lua(st) .func("get_netsync_read_permitted") .push_str(branch) - .push_str(identity()) + .push_str(identity.inner()()) .call(2,1) .extract_bool(permitted) .ok(); @@ -770,13 +771,13 @@ bool } bool -lua_hooks::hook_get_netsync_write_permitted(key_name const & identity) +lua_hooks::hook_get_netsync_write_permitted(key_id const & identity) { bool permitted = false, exec_ok = false; exec_ok = Lua(st) .func("get_netsync_write_permitted") - .push_str(identity()) + .push_str(identity.inner()()) .call(1,1) .extract_bool(permitted) .ok(); @@ -940,7 +941,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) @@ -953,14 +954,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()); + ll.push_str(i->first.inner()()); ll.set_field("key"); ll.push_str(i->second.first()); ll.set_field("name"); @@ -977,7 +978,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) @@ -990,14 +991,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()); + ll.push_str(i->first.inner()()); ll.set_field("key"); ll.push_str(i->second.first()); ll.set_field("name"); @@ -1012,13 +1013,13 @@ bool } bool -lua_hooks::hook_note_netsync_pubkey_received(key_name const & kid, +lua_hooks::hook_note_netsync_pubkey_received(key_id const & kid, size_t session_id) { Lua ll(st); ll .func("note_netsync_pubkey_received") - .push_str(kid()) + .push_str(kid.inner()()) .push_int(session_id); ll.call(2, 0); @@ -1026,13 +1027,13 @@ bool } bool -lua_hooks::hook_note_netsync_pubkey_sent(key_name const & kid, - size_t session_id) +lua_hooks::hook_note_netsync_pubkey_sent(key_id const & kid, + size_t session_id) { Lua ll(st); ll .func("note_netsync_pubkey_sent") - .push_str(kid()) + .push_str(kid.inner()()) .push_int(session_id); ll.call(2, 0); @@ -1041,7 +1042,7 @@ lua_hooks::hook_note_netsync_cert_receiv bool lua_hooks::hook_note_netsync_cert_received(revision_id const & rid, - key_name const & kid, + key_id const & kid, cert_name const & name, cert_value const & value, size_t session_id) @@ -1050,7 +1051,7 @@ lua_hooks::hook_note_netsync_cert_receiv ll .func("note_netsync_cert_received") .push_str(encode_hexenc(rid.inner()(), rid.inner().made_from)) - .push_str(kid()) + .push_str(kid.inner()()) .push_str(name()) .push_str(value()) .push_int(session_id); @@ -1061,7 +1062,7 @@ lua_hooks::hook_note_netsync_cert_sent(r bool lua_hooks::hook_note_netsync_cert_sent(revision_id const & rid, - key_name const & kid, + key_id const & kid, cert_name const & name, cert_value const & value, size_t session_id) @@ -1070,7 +1071,7 @@ lua_hooks::hook_note_netsync_cert_sent(r ll .func("note_netsync_cert_sent") .push_str(encode_hexenc(rid.inner()(), rid.inner().made_from)) - .push_str(kid()) + .push_str(kid.inner()()) .push_str(name()) .push_str(value()) .push_int(session_id); ============================================================ --- lua_hooks.hh 07356795d81fbfd324c6261089386e28b77c1b75 +++ lua_hooks.hh fe660f497db47dbd08c4324ab027ad54399b8e30 @@ -51,28 +51,28 @@ public: bool hook_get_branch_key(branch_name const & branchname, key_name & k); bool hook_get_passphrase(key_name const & k, std::string & phrase); bool hook_get_author(branch_name const & branchname, - key_name const & k, + key_id const & k, 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); - bool hook_accept_testresult_change(std::map const & old_results, - std::map const & new_results); + bool hook_accept_testresult_change(std::map const & old_results, + std::map const & new_results); // network hooks bool hook_get_netsync_key(utf8 const & server_address, globish const & include, globish const & exclude, - key_name & k); + key_id & k); bool hook_get_netsync_connect_command(uri const & u, globish const & include_pattern, globish const & exclude_pattern, @@ -81,10 +81,10 @@ public: bool hook_use_transport_auth(uri const & u); bool hook_get_netsync_read_permitted(std::string const & branch, - key_name const & identity); + key_id const & identity); // anonymous no-key version bool hook_get_netsync_read_permitted(std::string const & branch); - bool hook_get_netsync_write_permitted(key_name const & identity); + bool hook_get_netsync_write_permitted(key_id const & identity); // local repo hooks bool hook_ignore_file(file_path const & p); @@ -151,27 +151,27 @@ public: 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_name const & kid, + bool hook_note_netsync_pubkey_received(key_id const & kid, size_t session_id); - bool hook_note_netsync_pubkey_sent(key_name const & kid, + bool hook_note_netsync_pubkey_sent(key_id const & kid, size_t session_id); bool hook_note_netsync_cert_received(revision_id const & rid, - key_name const & kid, + key_id const & kid, cert_name const & name, cert_value const & value, size_t session_id); bool hook_note_netsync_cert_sent(revision_id const & rid, - key_name const & kid, + key_id const & kid, cert_name const & name, cert_value const & value, size_t session_id); ============================================================ --- migrate_ancestry.cc 60ea5e154f134f633e1405cbd1d312d46a68464c +++ migrate_ancestry.cc 20f631786b09b2c6c82effd5859813f175ce5e5f @@ -386,7 +386,7 @@ u64 anc_graph::add_node_for_oldstyle_rev // load certs vector rcerts; - db.get_revision_certs(rev, rcerts); + db.get_oldstyle_revision_certs(rev, rcerts); db.erase_bogus_certs(rcerts); for(vector::const_iterator i = rcerts.begin(); i != rcerts.end(); ++i) ============================================================ --- options_list.hh 04514511db1d6d12e25f355816b21203822c89b2 +++ options_list.hh e401fd89ec9c48336dcd009a59424b8eb3b39b97 @@ -380,10 +380,19 @@ OPTVAR(key, key_name, signing_key, ) OPTVAR(key, key_name, signing_key, ) +OPTVAR(key, key_id, signing_key_id, ) 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 + } } #endif @@ -398,7 +407,7 @@ 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 ============================================================ --- project.cc f5ceff7a0415cb87e9870999585459b42c71e4df +++ project.cc 04cff64a5a395861e915b0787e453d8bc332dc2e @@ -278,7 +278,7 @@ tag_t::tag_t(revision_id const & ident, tag_t::tag_t(revision_id const & ident, utf8 const & name, - key_name const & key) + key_id const & key) : ident(ident), name(name), key(key) {} @@ -366,11 +366,15 @@ project_t::put_standard_certs_from_optio string author = opts.author(); if (author.empty()) { - key_name key; + key_id key; get_user_key(opts, lua, db, keys, key); if (!lua.hook_get_author(branch, key, author)) - author = key(); + { + key_name name; + get_name_of_key(key, name); + author = name(); + } } put_standard_certs(keys, id, branch, changelog, date, author); ============================================================ --- project.hh e2f0f5db26a6d8bbe9214b264aca96b58513fcc8 +++ project.hh dee7f3ecb9b61646c3e8b296e38fa11d6081e763 @@ -47,8 +47,8 @@ public: public: revision_id ident; utf8 name; - key_name key; - tag_t(revision_id const & ident, utf8 const & name, key_name const & key); + key_id key; + tag_t(revision_id const & ident, utf8 const & name, key_id const & key); }; bool operator < (tag_t const & a, tag_t const & b); @@ -133,6 +133,17 @@ public: void put_revision_comment(key_store & keys, revision_id const & id, utf8 const & comment); + + // lookup the key ID associated with a particular key name + void lookup_key_by_name(key_name const & name, key_id & id); + // the reverse + 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 const & keys, + key_id const & id, + key_name & name); }; std::string ============================================================ --- update.cc a67ae873fc4fca77ae07922e0b6869fc837ae550 +++ update.cc 5f93a955ecd41f07490883ea0a76e01ec8cf7461 @@ -55,7 +55,7 @@ get_test_results_for_revision(project_t static void get_test_results_for_revision(project_t & project, revision_id const & id, - map & results) + map & results) { vector certs; project.get_revision_certs_by_name(id, cert_name(testresult_cert_name), @@ -81,7 +81,7 @@ acceptable_descendent(lua_hooks & lua, project_t & project, branch_name const & branch, revision_id const & base, - map & base_results, + map & base_results, revision_id const & target) { L(FL("Considering update target %s") % target); @@ -94,7 +94,7 @@ acceptable_descendent(lua_hooks & lua, } // step 2: check the testresults - map target_results; + map target_results; get_test_results_for_revision(project, target, target_results); if (lua.hook_accept_testresult_change(base_results, target_results)) { @@ -119,7 +119,7 @@ pick_update_candidates(lua_hooks & lua, I(!null_id(base)); I(!branch().empty()); - map base_results; + map base_results; get_test_results_for_revision(project, base, base_results); candidates.clear();