#
# add_file "key_store.cc"
#
# add_file "key_store.hh"
#
# patch "ChangeLog"
# from [21b992ed451a886bfd5ce7934d11bdbe4a9762e0]
# to [e3cb4410fbf089f5ba258314b15d2fb0494ec871]
#
# patch "Makefile.am"
# from [37d234104aa51fb9f169ed0be12208e4b5be0669]
# to [c3ca41e70b719d5d345383a893a7d4ba7823160c]
#
# patch "app_state.cc"
# from [4c8ba6a5cdc3fa945a945e19ea63e1fc857d3ca1]
# to [58db112140d05dcb5ffaea7e7eea44f04662312f]
#
# patch "app_state.hh"
# from [869c3e0393d765e37fc17ae117ccbbe69776b177]
# to [b310058ad20b794c7b4347eb35d495b980f149cd]
#
# patch "cert.cc"
# from [43de7f5240b7caa27fc590630afe3ffeea0bfa0b]
# to [fdf5188e96328a6d86fcac31ff3caf0b8ebb7602]
#
# patch "cert.hh"
# from [e2b1d86c8f2610e854afed7ab661c4c2554e7004]
# to [7e7e906bb36445343533611871cd5d3680cb7f99]
#
# patch "commands.cc"
# from [61185ae5cc7cd776c25ca1655199a314bdd40378]
# to [5e3307a36823404a734e65224da9966461d8e382]
#
# patch "database.cc"
# from [83c0e4fe4b672da030bc50966c118ac0c2c98017]
# to [a1452325ac8f6aef8804ec53785ecbac5ee4cea6]
#
# patch "database.hh"
# from [1ac20ac00fe3bb34f5a72c03d3abbfbc57f318b3]
# to [be5bc6fef85bbfd317b0d94d1b6329167a015a28]
#
# patch "file_io.cc"
# from [e39a1c13030c5378ea4cb3aa9621148ce0c8fb7d]
# to [d57bf07416e3446ccc8235334a0f890da2f12fc4]
#
# patch "file_io.hh"
# from [16f383f0e4eb6fa8454fce1071880f066fc69bdb]
# to [26fcbfa41357c4f16c935aaa6227808f35c292c6]
#
# patch "key_store.cc"
# from []
# to [05ee19ff4146a3ef4b9b1751e5dbf39a55f26a50]
#
# patch "key_store.hh"
# from []
# to [ed83144ff6fdb7f931e8f950b36362bf48b45273]
#
# patch "keys.cc"
# from [cf21506cfc9735f800dccf4d1c3b575fa97bab90]
# to [0a144d76856af7fe643c529d9d2536a197fe15cb]
#
# patch "keys.hh"
# from [16c620ec000b13c0ef656a92a59c18660d4c1aaf]
# to [ec2036295cdf27e6ac7994fb9952360c364221f6]
#
# patch "lua.cc"
# from [fc053070a0c0a106e6f9a3e5678ef2a427ad1fcd]
# to [05347870adbee4f4ceb65293c2b9d1ef7e7eb72a]
#
# patch "lua.hh"
# from [950e24bc4b2c16b258f00aee0c4923ae93f256df]
# to [a36a8bff73690208d4d879fc868696315881a465]
#
# patch "monotone.cc"
# from [21be582ccd322a35a5d1864ee1251e5773054619]
# to [a9105108afab139e9cad54cc92e5f5bf672f0594]
#
# patch "netsync.cc"
# from [c4933c5062e859a98b69e9dfa872b45a5be919da]
# to [f3d10c633250d6a96bc32d11859c6064d243772c]
#
# patch "options.hh"
# from [e3f8114ba090e819215b0b8b370181b273bf16cc]
# to [ac7bfa54b40a56f68dcdd40c83f994613aa7ab9f]
#
# patch "packet.cc"
# from [407e15cf1c485e09665a372588be2f99491a17d7]
# to [f4ca19df46ef590bb112762f222325ae2ddb98be]
#
# patch "packet.hh"
# from [ec7178c2332473305c0aa7d00c727e338fc7810d]
# to [aff613af14460ebbedebdbc0e95c3dfc136f5c02]
#
# patch "tests/t_cross.at"
# from [3c97886280aa50bb3dcef375373f9207175cc927]
# to [d4a0e27dcd1f8ad7859485a1785ed3e3ff7c0272]
#
# patch "tests/t_lua_privkey.at"
# from [e85cec14dbef01453f2307c787d8144502bfba77]
# to [4ab69dc88079acf06ee05abf7368abcab84019a9]
#
# patch "tests/t_netsync_absorbs.at"
# from [192d6c27f26a2553f8a0044c95832ae611861c49]
# to [754c3f6173c7f3a22380904f8dbc20c4174447c6]
#
# patch "tests/t_netsync_permissions.at"
# from [2b2fdda0e34c5c71bad5451e5acdec7416f54162]
# to [2e18d7f1e43cc50034a417b6ea6f18c79c5467c3]
#
# patch "tests/t_short_opts.at"
# from [65969eb19ec23c4f37e9583f6556104ac8e9f6d2]
# to [f633e5c60ec847a5b9cc42643e1be2d6c89788bd]
#
# patch "tests/t_subdirs.at"
# from [07ccac7d46f5adba7cc61ad03277398004d4232d]
# to [6dc74192163aea63aaa8796c6864ab291fb73120]
#
# patch "testsuite.at"
# from [9843a5c53ec471614fc6d5ef5dfcf16fc6995608]
# to [925c7087ae848ad85724183ab80d3a042686571d]
#
# patch "vocab.hh"
# from [22382ac1bdffec21170a88ff2580fe39b508243f]
# to [f14bf372280ec9b5bc886598249ec518dfa114d3]
#
========================================================================
--- ChangeLog 21b992ed451a886bfd5ce7934d11bdbe4a9762e0
+++ ChangeLog e3cb4410fbf089f5ba258314b15d2fb0494ec871
@@ -1,3 +1,25 @@
+2005-09-25 Timothy Brownawell
+
+ Move private keys outside the database.
+ They're now stored as keypairs in ~/.monotone/keys
+ Details:
+ * keystore.{cc,hh}: handle storage of keypairs
+ * tests*: Specify keystore location when running the testsuite.
+ This prevents it from polluting the user's keystore.
+ * database{cc,hh}: remove ability to put privkeys. They can still
+ be listed, retrieved, and deleted, to support
+ * commands.cc: New command, extract_keys. Copies private keys from
+ the database to the keystore.
+ * vocab.hh: add keypair type, like pair, except that
+ the members are named pub and priv.
+ * packet.cc: Clean up read_packets.
+ * packet.{cc,hh}: privkey packets no longer exists, handle keypair
+ packets instead.
+ * file_io.{cc,hh}: add read_directory because tree_walker needs to
+ be in the wc. add a write_data that works outside the wc.
+ * Makefile.am: add keystore.{cc,hh}
+ * others: update to work with new key storage
+
2005-09-21 Timothy Brownawell
* contrib/usher.cc: better error checking
========================================================================
--- Makefile.am 37d234104aa51fb9f169ed0be12208e4b5be0669
+++ Makefile.am c3ca41e70b719d5d345383a893a7d4ba7823160c
@@ -11,6 +11,7 @@
work.cc work.hh \
cert.cc cert.hh \
database.cc database.hh \
+ key_store.cc key_store.hh \
file_io.cc file_io.hh \
keys.cc keys.hh \
manifest.cc manifest.hh \
========================================================================
--- app_state.cc 4c8ba6a5cdc3fa945a945e19ea63e1fc857d3ca1
+++ app_state.cc 58db112140d05dcb5ffaea7e7eea44f04662312f
@@ -31,9 +31,11 @@
static string const database_option("database");
static string const branch_option("branch");
static string const key_option("key");
+static string const keydir_option("keydir");
app_state::app_state()
- : branch_name(""), db(system_path()), stdhooks(true), rcfiles(true), diffs(false),
+ : branch_name(""), db(system_path()), keys(this), stdhooks(true),
+ rcfiles(true), diffs(false),
no_merges(false), set_default(false), verbose(false), search_root("/"),
depth(-1), last(-1), diff_format(unified_diff), diff_args_provided(false),
use_lca(false), execute(false)
@@ -253,6 +255,14 @@
}
void
+app_state::set_key_dir(system_path const & filename)
+{
+ if (!filename.empty()) keys.set_key_dir(filename);
+
+ options[keydir_option] = filename.as_internal();
+}
+
+void
app_state::set_branch(utf8 const & branch)
{
branch_name = branch();
========================================================================
--- app_state.hh 869c3e0393d765e37fc17ae117ccbbe69776b177
+++ app_state.hh b310058ad20b794c7b4347eb35d495b980f149cd
@@ -20,6 +20,7 @@
#include "work.hh"
#include "vocab.hh"
#include "paths.hh"
+#include "key_store.hh"
// this class is supposed to hold all (or.. well, most) of the state of the
// application, barring some unfortunate static objects like the debugging /
@@ -34,6 +35,7 @@
utf8 branch_name;
database db;
lua_hooks lua;
+ key_store keys;
bool stdhooks;
bool rcfiles;
bool diffs;
@@ -92,6 +94,7 @@
void make_branch_sticky();
void set_database(system_path const & filename);
+ void set_key_dir(system_path const & filename);
void set_signing_key(utf8 const & key);
void set_root(system_path const & root);
void set_message(utf8 const & message);
========================================================================
--- cert.cc 43de7f5240b7caa27fc590630afe3ffeea0bfa0b
+++ cert.cc fdf5188e96328a6d86fcac31ff3caf0b8ebb7602
@@ -319,69 +319,71 @@
priv_key_exists(app_state & app, rsa_keypair_id const & id)
{
- if (app.db.private_key_exists(id))
+ if (app.keys.key_pair_exists(id))
return true;
-
- base64< arc4 > dummy;
- if (app.lua.hook_get_priv_key(id, dummy))
+ keypair kp;
+
+ if (app.lua.hook_get_key_pair(id, kp))
return true;
return false;
}
-// Loads a private key for a given key id, from either a lua hook
-// or the database. This will bomb out if the same keyid exists
+// Loads a key pair for a given key id, from either a lua hook
+// or the key store. This will bomb out if the same keyid exists
// in both with differing contents.
void
-load_priv_key(app_state & app,
+load_key_pair(app_state & app,
rsa_keypair_id const & id,
- base64< arc4 > & priv)
+ keypair & kp)
{
- static std::map > > privkeys;
- bool persist_ok = (!privkeys.empty()) || app.lua.hook_persist_phrase_ok();
+ static std::map keys;
+ bool persist_ok = (!keys.empty()) || app.lua.hook_persist_phrase_ok();
- if (persist_ok
- && privkeys.find(id) != privkeys.end())
+ if (persist_ok && keys.find(id) != keys.end())
{
- priv = privkeys[id];
+ kp = keys[id];
}
else
{
- base64< arc4 > dbkey, luakey;
- bool havedb = false, havelua = false;
+ keypair kskeys, luakeys;
+ bool haveks = false, havelua = false;
- if (app.db.private_key_exists(id))
+ if (app.keys.key_pair_exists(id))
{
- app.db.get_key(id, dbkey);
- havedb = true;
+ app.keys.get_key_pair(id, kskeys);
+ haveks = true;
}
- havelua = app.lua.hook_get_priv_key(id, luakey);
+ havelua = app.lua.hook_get_key_pair(id, luakeys);
- N(havedb || havelua,
- F("no private key '%s' found in database or get_priv_key hook") % id);
+ N(haveks || havelua,
+ F("no private key '%s' found in key store or get_priv_key hook") % id);
if (havelua)
{
- if (havedb)
+ if (haveks)
{
// We really don't want the database key and the rcfile key
// to differ.
- N(keys_match(id, dbkey, id, luakey),
- F("mismatch between private key '%s' in database"
- " and get_priv_key hook") % id);
+ N(keys_match(id, kskeys.priv, id, luakeys.priv)
+ && keys_match(id, kskeys.pub, id, luakeys.pub),
+ F("mismatch between key '%s' in key store"
+ " and get_key_pair hook") % id);
}
- priv = luakey;
+ kp = luakeys;
}
- else if (havedb)
+ else if (haveks)
{
- priv = dbkey;
+ kp = kskeys;
}
if (persist_ok)
- privkeys.insert(make_pair(id, priv));
+ {
+ keys.insert(make_pair(id, kp));
+ }
}
}
@@ -389,12 +391,14 @@
calculate_cert(app_state & app, cert & t)
{
string signed_text;
- base64< arc4 > priv;
+ keypair kp;
cert_signable_text(t, signed_text);
- load_priv_key(app, t.key, priv);
+ load_key_pair(app, t.key, kp);
+ if (!app.db.public_key_exists(t.key))
+ app.db.put_key(t.key, kp.pub);
- make_signature(app, t.key, priv, signed_text, t.sig);
+ make_signature(app, t.key, kp.priv, signed_text, t.sig);
}
cert_status
@@ -452,7 +456,7 @@
}
vector all_privkeys;
- app.db.get_private_keys(all_privkeys);
+ app.keys.get_keys(all_privkeys);
if (all_privkeys.size() != 1)
return false;
else
========================================================================
--- cert.hh e2b1d86c8f2610e854afed7ab661c4c2554e7004
+++ cert.hh 7e7e906bb36445343533611871cd5d3680cb7f99
@@ -55,9 +55,9 @@
void cert_signable_text(cert const & t,std::string & out);
cert_status check_cert(app_state & app, cert const & t);
bool priv_key_exists(app_state & app, rsa_keypair_id const & id);
-void load_priv_key(app_state & app,
- rsa_keypair_id const & id,
- base64< arc4 > & priv);
+void load_key_pair(app_state & app,
+ rsa_keypair_id const & id,
+ keypair & kp);
void calculate_cert(app_state & app, cert & t);
void make_simple_cert(hexenc const & id,
cert_name const & nm,
========================================================================
--- commands.cc 61185ae5cc7cd776c25ca1655199a314bdd40378
+++ commands.cc 5e3307a36823404a734e65224da9966461d8e382
@@ -608,9 +608,15 @@
transaction_guard guard(app.db);
if (args.size() == 0)
- app.db.get_key_ids("", pubkeys, privkeys);
+ {
+ app.db.get_key_ids("", pubkeys);
+ app.keys.get_key_ids("", privkeys);
+ }
else if (args.size() == 1)
- app.db.get_key_ids(idx(args, 0)(), pubkeys, privkeys);
+ {
+ app.db.get_key_ids(idx(args, 0)(), pubkeys);
+ app.keys.get_key_ids(idx(args, 0)(), privkeys);
+ }
else
throw usage(name);
@@ -636,10 +642,10 @@
for (size_t i = 0; i < privkeys.size(); ++i)
{
rsa_keypair_id keyid = idx(privkeys, i)();
- base64< arc4 > priv_encoded;
+ keypair kp;
hexenc hash_code;
- app.db.get_key(keyid, priv_encoded);
- key_hash_code(keyid, priv_encoded, hash_code);
+ app.keys.get_key_pair(keyid, kp);
+ key_hash_code(keyid, kp.priv, hash_code);
cout << hash_code << " " << keyid << endl;
}
cout << endl;
@@ -808,15 +814,14 @@
rsa_keypair_id ident;
internalize_rsa_keypair_id(idx(args, 0), ident);
- N(! app.db.key_exists(ident),
- F("key '%s' already exists in database") % ident);
+ N(! (app.db.public_key_exists(ident) || app.keys.key_pair_exists(ident)),
+ F("key '%s' already exists") % ident);
- base64 pub;
- base64< arc4 > priv;
+ keypair kp;
P(F("generating key-pair '%s'\n") % ident);
- generate_key_pair(app.lua, ident, pub, priv);
+ generate_key_pair(app.lua, ident, kp);
P(F("storing key-pair '%s' in database\n") % ident);
- app.db.put_key_pair(ident, pub, priv);
+ app.keys.put_key_pair(ident, kp);
guard.commit();
}
@@ -847,8 +852,15 @@
key_deleted = true;
}
+ if (app.keys.key_pair_exists(ident))
+ {
+ P(F("dropping key pair '%s' from key store\n\n") % ident);
+ app.keys.delete_key(ident);
+ key_deleted = true;
+ }
+
N(key_deleted,
- F("public or private key '%s' does not exist in database") % idx(args, 0)());
+ F("public or private key '%s' does not exist") % idx(args, 0)());
guard.commit();
}
@@ -864,14 +876,14 @@
rsa_keypair_id ident;
internalize_rsa_keypair_id(idx(args, 0), ident);
- N(app.db.key_exists(ident),
- F("key '%s' does not exist in database") % ident);
+ N(app.keys.key_pair_exists(ident),
+ F("key '%s' does not exist in the key store") % ident);
- base64< arc4 > key;
- app.db.get_key(ident, key);
- change_key_passphrase(app.lua, ident, key);
- app.db.delete_private_key(ident);
- app.db.put_key(ident, key);
+ keypair key;
+ app.keys.get_key_pair(ident, key);
+ change_key_passphrase(app.lua, ident, key.priv);
+ app.keys.delete_key(ident);
+ app.keys.put_key_pair(ident, key);
P(F("passphrase changed\n"));
guard.commit();
@@ -910,7 +922,7 @@
encode_base64(val, val_encoded);
cert t(ident, name, val_encoded, key);
-
+
packet_db_writer dbw(app);
calculate_cert(app, t);
dbw.consume_revision_cert(revision(t));
@@ -1807,12 +1819,24 @@
throw usage(name);
rsa_keypair_id ident(idx(args, 0)());
- N(app.db.public_key_exists(ident),
- F("public key '%s' does not exist in database") % idx(args, 0)());
+ bool exists(false);
+ base64< rsa_pub_key > key;
+ if (app.db.public_key_exists(ident))
+ {
+ app.db.get_key(ident, key);
+ exists = true;
+ }
+ if (app.keys.key_pair_exists(ident))
+ {
+ keypair kp;
+ app.keys.get_key_pair(ident, kp);
+ key = kp.pub;
+ exists = true;
+ }
+ N(exists,
+ F("public key '%s' does not exist") % idx(args, 0)());
packet_writer pw(cout);
- base64< rsa_pub_key > key;
- app.db.get_key(ident, key);
pw.consume_public_key(ident, key);
}
@@ -1823,16 +1847,14 @@
throw usage(name);
rsa_keypair_id ident(idx(args, 0)());
- N(app.db.private_key_exists(ident) && app.db.private_key_exists(ident),
- F("public and private key '%s' do not exist in database") % idx(args, 0)());
+ N(app.keys.key_pair_exists(ident),
+ F("public and private key '%s' do not exist in key store")
+ % idx(args, 0)());
packet_writer pw(cout);
- base64< arc4 > privkey;
- base64< rsa_pub_key > pubkey;
- app.db.get_key(ident, privkey);
- app.db.get_key(ident, pubkey);
- pw.consume_public_key(ident, pubkey);
- pw.consume_private_key(ident, privkey);
+ keypair kp;
+ app.keys.get_key_pair(ident, kp);
+ pw.consume_key_pair(ident, kp);
}
@@ -3729,4 +3751,20 @@
app.db.clear_var(k);
}
+CMD(extract_keys, N_("debug"), N_(""),
+ N_("copy all private keys in the database into the keystore"),
+ OPT_NONE)
+{
+ std::vector privkeys;
+ app.db.get_private_keys(privkeys);
+ for (std::vector::const_iterator i = privkeys.begin();
+ i != privkeys.end(); ++i)
+ {
+ keypair kp;
+ app.db.get_key(*i, kp.priv);
+ app.db.get_key(*i, kp.pub);
+ app.keys.put_key_pair(*i, kp);
+ }
+}
+
}; // namespace commands
========================================================================
--- database.cc 83c0e4fe4b672da030bc50966c118ac0c2c98017
+++ database.cc a1452325ac8f6aef8804ec53785ecbac5ee4cea6
@@ -1446,11 +1446,9 @@
void
database::get_key_ids(string const & pattern,
- vector & pubkeys,
- vector & privkeys)
+ vector & pubkeys)
{
pubkeys.clear();
- privkeys.clear();
results res;
if (pattern != "")
@@ -1463,17 +1461,6 @@
for (size_t i = 0; i < res.size(); ++i)
pubkeys.push_back(res[i][0]);
-
- if (pattern != "")
- fetch(res, one_col, any_rows,
- "SELECT id FROM private_keys WHERE id GLOB ?",
- pattern.c_str());
- else
- fetch(res, one_col, any_rows,
- "SELECT id FROM private_keys");
-
- for (size_t i = 0; i < res.size(); ++i)
- privkeys.push_back(res[i][0]);
}
void
@@ -1488,15 +1475,15 @@
}
void
-database::get_private_keys(vector & keys)
+database::get_public_keys(vector & keys)
{
- get_keys("private_keys", keys);
+ get_keys("public_keys", keys);
}
-void
-database::get_public_keys(vector & keys)
+void
+database::get_private_keys(vector & keys)
{
- get_keys("public_keys", keys);
+ get_keys("private_keys", keys);
}
bool
@@ -1525,7 +1512,7 @@
return false;
}
-bool
+bool
database::private_key_exists(rsa_keypair_id const & id)
{
results res;
@@ -1538,11 +1525,6 @@
return false;
}
-bool
-database::key_exists(rsa_keypair_id const & id)
-{
- return public_key_exists(id) || private_key_exists(id);
-}
void
database::get_pubkey(hexenc const & hash,
@@ -1569,17 +1551,6 @@
}
void
-database::get_key(rsa_keypair_id const & priv_id,
- base64< arc4 > & priv_encoded)
-{
- results res;
- fetch(res, one_col, one_col,
- "SELECT keydata FROM private_keys WHERE id = ?",
- priv_id().c_str());
- priv_encoded = res[0][0];
-}
-
-void
database::put_key(rsa_keypair_id const & pub_id,
base64 const & pub_encoded)
{
@@ -1592,29 +1563,17 @@
thash().c_str(), pub_id().c_str(), pub_encoded().c_str());
}
-void
-database::put_key(rsa_keypair_id const & priv_id,
- base64< arc4 > const & priv_encoded)
+void
+database::get_key(rsa_keypair_id const & priv_id,
+ base64< arc4 > & priv_encoded)
{
- hexenc thash;
- key_hash_code(priv_id, priv_encoded, thash);
- E(!private_key_exists(priv_id),
- F("another key with name '%s' already exists") % priv_id);
- execute("INSERT INTO private_keys VALUES(?, ?, ?)",
- thash().c_str(), priv_id().c_str(), priv_encoded().c_str());
+ results res;
+ fetch(res, one_col, one_col,
+ "SELECT keydata FROM private_keys WHERE id = ?",
+ priv_id().c_str());
+ priv_encoded = res[0][0];
}
-void
-database::put_key_pair(rsa_keypair_id const & id,
- base64 const & pub_encoded,
- base64< arc4 > const & priv_encoded)
-{
- transaction_guard guard(*this);
- put_key(id, pub_encoded);
- put_key(id, priv_encoded);
- guard.commit();
-}
-
void
database::delete_private_key(rsa_keypair_id const & pub_id)
{
========================================================================
--- database.hh 1ac20ac00fe3bb34f5a72c03d3abbfbc57f318b3
+++ database.hh be5bc6fef85bbfd317b0d94d1b6329167a015a28
@@ -318,17 +318,16 @@
// crypto key / cert operations
void get_key_ids(std::string const & pattern,
- std::vector & pubkeys,
- std::vector & privkeys);
+ std::vector & pubkeys);
void get_private_keys(std::vector & privkeys);
+
void get_public_keys(std::vector & pubkeys);
- bool key_exists(rsa_keypair_id const & id);
-
bool public_key_exists(hexenc const & hash);
bool public_key_exists(rsa_keypair_id const & id);
bool private_key_exists(rsa_keypair_id const & id);
+
void get_pubkey(hexenc const & hash,
rsa_keypair_id & id,
@@ -337,20 +336,13 @@
void get_key(rsa_keypair_id const & id,
base64 & pub_encoded);
- void get_key(rsa_keypair_id const & id,
- base64< arc4 > & priv_encoded);
-
void put_key(rsa_keypair_id const & id,
base64 const & pub_encoded);
-
- void put_key(rsa_keypair_id const & id,
- base64< arc4 > const & priv_encoded);
-
- void put_key_pair(rsa_keypair_id const & pub_id,
- base64 const & pub_encoded,
- base64< arc4 > const & priv_encoded);
+ void get_key(rsa_keypair_id const & id,
+ base64< arc4 > & priv_encoded);
void delete_private_key(rsa_keypair_id const & pub_id);
+
void delete_public_key(rsa_keypair_id const & pub_id);
// note: this section is ridiculous. please do something about it.
========================================================================
--- file_io.cc e39a1c13030c5378ea4cb3aa9621148ce0c8fb7d
+++ file_io.cc d57bf07416e3446ccc8235334a0f890da2f12fc4
@@ -315,7 +315,30 @@
dat = tmp2;
}
+void read_directory(system_path const & path,
+ std::vector & files,
+ std::vector & dirs)
+{
+ files.clear();
+ dirs.clear();
+ fs::directory_iterator ei;
+ for(fs::directory_iterator di(path.as_external());
+ di != ei; ++di)
+ {
+ fs::path entry = *di;
+ if (!fs::exists(entry)
+ || di->string() == "."
+ || di->string() == "..")
+ continue;
+ if (fs::is_directory(entry))
+ dirs.push_back(utf8(entry.leaf()));
+ else
+ files.push_back(utf8(entry.leaf()));
+ }
+}
+
+
// This function can only be called once per run.
static void
read_data_stdin(data & dat)
@@ -348,18 +371,13 @@
static void
write_data_impl(any_path const & p,
- data const & dat)
+ data const & dat,
+ any_path const & tmp)
{
N(!directory_exists(p),
F("file '%s' cannot be overwritten as data; it is a directory") % p);
make_dir_for(p);
-
- // we write, non-atomically, to MT/data.tmp.
- // nb: no mucking around with multiple-writer conditions. we're a
- // single-user single-threaded program. you get what you paid for.
- assert_path_is_directory(bookkeeping_root);
- bookkeeping_path tmp = bookkeeping_root / "data.tmp";
{
// data.tmp opens
@@ -376,6 +394,18 @@
fs::rename(mkdir(tmp), mkdir(p));
}
+static void
+write_data_impl(any_path const & p,
+ data const & dat)
+{
+ // we write, non-atomically, to MT/data.tmp.
+ // nb: no mucking around with multiple-writer conditions. we're a
+ // single-user single-threaded program. you get what you paid for.
+ assert_path_is_directory(bookkeeping_root);
+ bookkeeping_path tmp = bookkeeping_root / "data.tmp";
+ write_data_impl(p, dat, tmp);
+}
+
void
write_data(file_path const & path, data const & dat)
{
@@ -416,6 +446,14 @@
write_data(path, data(tmp2));
}
+void
+write_data(system_path const & path,
+ data const & data,
+ system_path const & tmpdir)
+{
+ write_data_impl(path, data, tmpdir / "data.tmp");
+}
+
tree_walker::~tree_walker() {}
static void
========================================================================
--- file_io.hh 16f383f0e4eb6fa8454fce1071880f066fc69bdb
+++ file_io.hh 26fcbfa41357c4f16c935aaa6227808f35c292c6
@@ -69,6 +69,10 @@
data & dat,
lua_hooks & lua);
+void read_directory(system_path const & path,
+ std::vector & files,
+ std::vector & dirs);
+
// This function knows that "-" means "stdin".
void read_data_for_command_line(utf8 const & path, data & dat);
@@ -83,6 +87,14 @@
data const & dat,
lua_hooks & lua);
+// Version that takes a system_path. To work with the "somewhat atomic"
+// goal, it also takes as an argument the place to put the temp file. Whoever
+// uses this is responsible to make sure that the tmpdir argument is somewhere
+// that the file can be atomically renamed from (same file system)
+void write_data(system_path const & path,
+ data const & data,
+ system_path const & tmpdir);
+
class tree_walker
{
public:
========================================================================
--- key_store.cc
+++ key_store.cc 05ee19ff4146a3ef4b9b1751e5dbf39a55f26a50
@@ -0,0 +1,228 @@
+#include
+
+#include "key_store.hh"
+#include "file_io.hh"
+#include "packet.hh"
+#include "keys.hh"
+#include "globish.hh"
+
+struct keyreader : public packet_consumer
+{
+ key_store * ks;
+
+ keyreader(key_store * k): ks(k) {}
+ virtual void consume_file_data(file_id const & ident,
+ file_data const & dat)
+ {E(false, F("Extraneous data in key store."));}
+ virtual void consume_file_delta(file_id const & id_old,
+ file_id const & id_new,
+ file_delta const & del)
+ {E(false, F("Extraneous data in key store."));}
+ virtual void consume_file_reverse_delta(file_id const & id_new,
+ file_id const & id_old,
+ file_delta const & del)
+ {E(false, F("Extraneous data in key store."));}
+
+
+ virtual void consume_manifest_data(manifest_id const & ident,
+ manifest_data const & dat)
+ {E(false, F("Extraneous data in key store."));}
+ virtual void consume_manifest_delta(manifest_id const & id_old,
+ manifest_id const & id_new,
+ manifest_delta const & del)
+ {E(false, F("Extraneous data in key store."));}
+ virtual void consume_manifest_reverse_delta(manifest_id const & id_new,
+ manifest_id const & id_old,
+ manifest_delta const & del)
+ {E(false, F("Extraneous data in key store."));}
+
+
+ virtual void consume_revision_data(revision_id const & ident,
+ revision_data const & dat)
+ {E(false, F("Extraneous data in key store."));}
+ virtual void consume_revision_cert(revision const & t)
+ {E(false, F("Extraneous data in key store."));}
+
+
+ virtual void consume_public_key(rsa_keypair_id const & ident,
+ base64< rsa_pub_key > const & k)
+ {E(false, F("Extraneous data in key store."));}
+
+ virtual void consume_key_pair(rsa_keypair_id const & ident,
+ keypair const & kp)
+ {
+ E(!ks->key_pair_exists(ident),
+ F("Key store has multiple keys with id '%s'.") % ident);
+ ks->keys.insert(std::make_pair(ident, kp));
+ hexenc hash;
+ key_hash_code(ident, kp.pub, hash);
+ ks->hashes.insert(std::make_pair(hash, ident));
+ L(F("Read key pair '%s' from key store.") % ident);
+ }
+};
+
+key_store::key_store(app_state * a): have_read(false), app(a)
+{
+ key_dir = system_path(get_homedir()) / ".monotone/keys";
+}
+void
+key_store::set_key_dir(system_path const & kd)
+{
+ key_dir = kd;
+}
+
+void
+key_store::read_key_dir()
+{
+ std::vector key_files, dirs;
+ if (directory_exists(key_dir))
+ read_directory(key_dir, key_files, dirs);
+ keyreader kr(this);
+ for (std::vector::const_iterator i = key_files.begin();
+ i != key_files.end(); ++i)
+ {
+ data dat;
+ read_data(key_dir / (*i)(), dat);
+ std::istringstream is(dat());
+ read_packets(is, kr);
+ }
+}
+
+void
+key_store::maybe_read_key_dir()
+{
+ if (have_read)
+ return;
+ have_read = true;
+ read_key_dir();
+}
+
+void
+key_store::ensure_in_database(rsa_keypair_id const & ident)
+{
+ maybe_read_key_dir();
+ if (app->db.public_key_exists(ident))
+ return;
+ std::map::iterator i = keys.find(ident);
+ I(i != keys.end());
+ app->db.put_key(ident, i->second.pub);
+}
+
+bool
+key_store::try_ensure_in_db(hexenc const & hash)
+{
+ std::map, rsa_keypair_id>::const_iterator i = hashes.find(hash);
+ if (i == hashes.end())
+ return false;
+ ensure_in_database(i->second);
+ return true;
+}
+
+void
+key_store::get_key_ids(std::string const & pattern,
+ std::vector & priv)
+{
+ maybe_read_key_dir();
+ priv.clear();
+ utf8 inc(pattern);
+ if (pattern.empty())
+ inc = utf8("*");
+ globish_matcher gm(inc, utf8(""));
+ for (std::map::const_iterator
+ i = keys.begin(); i != keys.end(); ++i)
+ {
+ if (gm((i->first)()))
+ priv.push_back(i->first);
+ }
+}
+
+void
+key_store::get_keys(std::vector & priv)
+{
+ maybe_read_key_dir();
+ priv.clear();
+ for (std::map::const_iterator
+ i = keys.begin(); i != keys.end(); ++i)
+ {
+ priv.push_back(i->first);
+ }
+}
+
+bool
+key_store::key_pair_exists(rsa_keypair_id const & ident)
+{
+ maybe_read_key_dir();
+ return keys.find(ident) != keys.end();
+}
+
+void
+key_store::get_key_pair(rsa_keypair_id const & ident,
+ keypair & kp)
+{
+ maybe_read_key_dir();
+ std::map::const_iterator i = keys.find(ident);
+ I(i != keys.end());
+ kp = i->second;
+}
+
+namespace
+{
+ // filename is the keypair id, except that some characters can't be put in
+ // filenames (especially on windows).
+ void
+ get_filename(rsa_keypair_id const & ident, std::string & filename)
+ {
+ filename = ident();
+ for (unsigned int i = 0; i < filename.size(); ++i)
+ if (std::string("+").find(filename[i]) != std::string::npos)
+ filename.at(i) = '_';
+ }
+}
+
+void
+key_store::get_key_file(rsa_keypair_id const & ident,
+ system_path & file)
+{
+ std::string leaf;
+ get_filename(ident, leaf);
+ file = key_dir / leaf;
+}
+
+void
+key_store::write_key(rsa_keypair_id const & ident)
+{
+ keypair kp;
+ get_key_pair(ident, kp);
+ std::ostringstream oss;
+ packet_writer pw(oss);
+ pw.consume_key_pair(ident, kp);
+ data dat(oss.str());
+ system_path file;
+ get_key_file(ident, file);
+ write_data(file, dat, key_dir);
+}
+
+void
+key_store::put_key_pair(rsa_keypair_id const & ident,
+ keypair const & kp)
+{
+ maybe_read_key_dir();
+ L(F("putting key pair '%s'") % ident);
+ I(keys.insert(std::make_pair(ident, kp)).second);
+ hexenc hash;
+ key_hash_code(ident, kp.pub, hash);
+ I(hashes.insert(std::make_pair(hash, ident)).second);
+ write_key(ident);
+}
+
+void
+key_store::delete_key(rsa_keypair_id const & ident)
+{
+ maybe_read_key_dir();
+ std::map::iterator i = keys.find(ident);
+ if (i != keys.end())
+ keys.erase(i);
+ system_path file;
+ get_key_file(ident, file);
+ delete_file(file);
+}
========================================================================
--- key_store.hh
+++ key_store.hh ed83144ff6fdb7f931e8f950b36362bf48b45273
@@ -0,0 +1,50 @@
+#ifndef __KEY_STORE_H__
+#define __KEY_STORE_H__
+
+#include