monotone

monotone Mtn Source Tree

Root/key_store.cc

1#include <sstream>
2
3#include "key_store.hh"
4#include "file_io.hh"
5#include "packet.hh"
6#include "keys.hh"
7#include "globish.hh"
8
9using std::make_pair;
10using std::istringstream;
11using std::map;
12using std::ostringstream;
13using std::pair;
14using std::string;
15using std::vector;
16
17struct keyreader : public packet_consumer
18{
19 key_store * ks;
20
21 keyreader(key_store * k): ks(k) {}
22 virtual void consume_file_data(file_id const & ident,
23 file_data const & dat)
24 {E(false, F("Extraneous data in key store."));}
25 virtual void consume_file_delta(file_id const & id_old,
26 file_id const & id_new,
27 file_delta const & del)
28 {E(false, F("Extraneous data in key store."));}
29
30 virtual void consume_revision_data(revision_id const & ident,
31 revision_data const & dat)
32 {E(false, F("Extraneous data in key store."));}
33 virtual void consume_revision_cert(revision<cert> const & t)
34 {E(false, F("Extraneous data in key store."));}
35
36
37 virtual void consume_public_key(rsa_keypair_id const & ident,
38 base64< rsa_pub_key > const & k)
39 {E(false, F("Extraneous data in key store."));}
40
41 virtual void consume_key_pair(rsa_keypair_id const & ident,
42 keypair const & kp)
43 {
44 L(FL("reading key pair '%s' from key store") % ident);
45 E(!ks->key_pair_exists(ident),
46 F("Key store has multiple keys with id '%s'.") % ident);
47 ks->keys.insert(make_pair(ident, kp));
48 hexenc<id> hash;
49 key_hash_code(ident, kp.pub, hash);
50 ks->hashes.insert(make_pair(hash, ident));
51 L(FL("successfully read key pair '%s' from key store") % ident);
52 }
53};
54
55key_store::key_store(app_state * a): have_read(false), app(a)
56{
57}
58
59void
60key_store::set_key_dir(system_path const & kd)
61{
62 key_dir = kd;
63}
64
65system_path const &
66key_store::get_key_dir()
67{
68 return key_dir;
69}
70
71void
72key_store::read_key_dir()
73{
74 vector<utf8> key_files, dirs;
75 if (directory_exists(key_dir))
76 {
77 L(FL("reading key dir '%s'") % key_dir);
78 read_directory(key_dir, key_files, dirs);
79 }
80 else
81 L(FL("key dir '%s' does not exist") % key_dir);
82 keyreader kr(this);
83 for (vector<utf8>::const_iterator i = key_files.begin();
84 i != key_files.end(); ++i)
85 {
86 L(FL("reading keys from file '%s'") % (*i));
87 data dat;
88 read_data(key_dir / (*i)(), dat);
89 istringstream is(dat());
90 read_packets(is, kr, *app);
91 }
92}
93
94void
95key_store::maybe_read_key_dir()
96{
97 if (have_read)
98 return;
99 have_read = true;
100 read_key_dir();
101}
102
103void
104key_store::ensure_in_database(rsa_keypair_id const & ident)
105{
106 maybe_read_key_dir();
107 if (app->db.public_key_exists(ident))
108 {
109 L(FL("public key '%s' is already in db, not loading") % ident);
110 return;
111 }
112 map<rsa_keypair_id, keypair>::iterator i = keys.find(ident);
113 I(i != keys.end());
114 app->db.put_key(ident, i->second.pub);
115 L(FL("loaded public key '%s' into db") % ident);
116}
117
118bool
119key_store::try_ensure_in_db(hexenc<id> const & hash)
120{
121 map<hexenc<id>, rsa_keypair_id>::const_iterator i = hashes.find(hash);
122 if (i == hashes.end())
123 return false;
124 ensure_in_database(i->second);
125 return true;
126}
127
128void
129key_store::get_key_ids(string const & pattern,
130 vector<rsa_keypair_id> & priv)
131{
132 maybe_read_key_dir();
133 priv.clear();
134 globish inc(pattern);
135 if (pattern.empty())
136 inc = globish("*");
137 globish_matcher gm(inc, globish(""));
138 for (map<rsa_keypair_id, keypair>::const_iterator
139 i = keys.begin(); i != keys.end(); ++i)
140 {
141 if (gm((i->first)()))
142 priv.push_back(i->first);
143 }
144}
145
146void
147key_store::get_keys(vector<rsa_keypair_id> & priv)
148{
149 maybe_read_key_dir();
150 priv.clear();
151 for (map<rsa_keypair_id, keypair>::const_iterator
152 i = keys.begin(); i != keys.end(); ++i)
153 {
154 priv.push_back(i->first);
155 }
156}
157
158bool
159key_store::key_pair_exists(rsa_keypair_id const & ident)
160{
161 maybe_read_key_dir();
162 return keys.find(ident) != keys.end();
163}
164
165void
166key_store::get_key_pair(rsa_keypair_id const & ident,
167 keypair & kp)
168{
169 maybe_read_key_dir();
170 map<rsa_keypair_id, keypair>::const_iterator i = keys.find(ident);
171 I(i != keys.end());
172 kp = i->second;
173}
174
175namespace
176{
177 // filename is the keypair id, except that some characters can't be put in
178 // filenames (especially on windows).
179 void
180 get_filename(rsa_keypair_id const & ident, string & filename)
181 {
182 filename = ident();
183 for (unsigned int i = 0; i < filename.size(); ++i)
184 if (string("+").find(filename[i]) != string::npos)
185 filename.at(i) = '_';
186 }
187}
188
189void
190key_store::get_key_file(rsa_keypair_id const & ident,
191 system_path & file)
192{
193 string leaf;
194 get_filename(ident, leaf);
195 file = key_dir / leaf;
196}
197
198void
199key_store::write_key(rsa_keypair_id const & ident)
200{
201 keypair kp;
202 get_key_pair(ident, kp);
203 ostringstream oss;
204 packet_writer pw(oss);
205 pw.consume_key_pair(ident, kp);
206 data dat(oss.str());
207 system_path file;
208 get_key_file(ident, file);
209 L(FL("writing key '%s' to file '%s' in dir '%s'") % ident % file % key_dir);
210 write_data(file, dat, key_dir);
211}
212
213void
214key_store::put_key_pair(rsa_keypair_id const & ident,
215 keypair const & kp)
216{
217 maybe_read_key_dir();
218 L(FL("putting key pair '%s'") % ident);
219 pair<map<rsa_keypair_id, keypair>::iterator, bool> res;
220 res = keys.insert(make_pair(ident, kp));
221 if (res.second)
222 {
223 hexenc<id> hash;
224 key_hash_code(ident, kp.pub, hash);
225 I(hashes.insert(make_pair(hash, ident)).second);
226 write_key(ident);
227 }
228 else
229 {
230 E(/*keys_match(ident, res.first->second.priv, ident, kp.priv)
231 && */keys_match(ident, res.first->second.pub, ident, kp.pub),
232 F("Cannot store key '%s'; a different key by that name exists.")
233 % ident);
234 }
235}
236
237void
238key_store::delete_key(rsa_keypair_id const & ident)
239{
240 maybe_read_key_dir();
241 map<rsa_keypair_id, keypair>::iterator i = keys.find(ident);
242 if (i != keys.end())
243 {
244 hexenc<id> hash;
245 key_hash_code(ident, i->second.pub, hash);
246 map<hexenc<id>, rsa_keypair_id>::iterator j = hashes.find(hash);
247 I(j != hashes.end());
248 hashes.erase(j);
249 keys.erase(i);
250 }
251 system_path file;
252 get_key_file(ident, file);
253 delete_file(file);
254}
255
256// Local Variables:
257// mode: C++
258// fill-column: 76
259// c-file-style: "gnu"
260// indent-tabs-mode: nil
261// End:
262// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status