monotone

monotone Mtn Source Tree

Root/cmd_key_cert.cc

1// Copyright (C) 2002 Graydon Hoare <graydon@pobox.com>
2//
3// This program is made available under the GNU GPL version 2.0 or
4// greater. See the accompanying file COPYING for details.
5//
6// This program is distributed WITHOUT ANY WARRANTY; without even the
7// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8// PURPOSE.
9
10#include "base.hh"
11#include <iostream>
12#include <sstream>
13#include <fstream>
14#include <iterator>
15
16#include "charset.hh"
17#include "cmd.hh"
18#include "app_state.hh"
19#include "database.hh"
20#include "project.hh"
21#include "keys.hh"
22#include "key_store.hh"
23#include "transforms.hh"
24
25using std::cout;
26using std::ostream_iterator;
27using std::ostringstream;
28using std::set;
29using std::string;
30using std::ofstream;
31
32CMD(genkey, "genkey", "", CMD_REF(key_and_cert), N_("KEYID"),
33 N_("Generates an RSA key-pair"),
34 "",
35 options::opts::none)
36{
37 database db(app);
38 key_store keys(app);
39
40 if (args.size() != 1)
41 throw usage(execid);
42
43 rsa_keypair_id ident;
44 internalize_rsa_keypair_id(idx(args, 0), ident);
45
46 keys.create_key_pair(db, ident);
47}
48
49CMD(dropkey, "dropkey", "", CMD_REF(key_and_cert), N_("KEYID"),
50 N_("Drops a public and/or private key"),
51 "",
52 options::opts::none)
53{
54 database db(app);
55 key_store keys(app);
56 bool key_deleted = false;
57 bool checked_db = false;
58
59 if (args.size() != 1)
60 throw usage(execid);
61
62 rsa_keypair_id ident(idx(args, 0)());
63 if (db.database_specified())
64 {
65 transaction_guard guard(db);
66 if (db.public_key_exists(ident))
67 {
68 P(F("dropping public key '%s' from database") % ident);
69 db.delete_public_key(ident);
70 key_deleted = true;
71 }
72 guard.commit();
73 checked_db = true;
74 }
75
76 if (keys.key_pair_exists(ident))
77 {
78 P(F("dropping key pair '%s' from keystore") % ident);
79 keys.delete_key(ident);
80 key_deleted = true;
81 }
82
83 i18n_format fmt;
84 if (checked_db)
85 fmt = F("public or private key '%s' does not exist "
86 "in keystore or database");
87 else
88 fmt = F("public or private key '%s' does not exist "
89 "in keystore, and no database was specified");
90 N(key_deleted, fmt % idx(args, 0)());
91}
92
93CMD(passphrase, "passphrase", "", CMD_REF(key_and_cert), N_("KEYID"),
94 N_("Changes the passphrase of a private RSA key"),
95 "",
96 options::opts::none)
97{
98 key_store keys(app);
99
100 if (args.size() != 1)
101 throw usage(execid);
102
103 rsa_keypair_id ident;
104 internalize_rsa_keypair_id(idx(args, 0), ident);
105
106 keys.change_key_passphrase(ident);
107 P(F("passphrase changed"));
108}
109
110CMD(ssh_agent_export, "ssh_agent_export", "", CMD_REF(key_and_cert),
111 N_("[FILENAME]"),
112 N_("Exports a private key for use with ssh-agent"),
113 "",
114 options::opts::none)
115{
116 database db(app);
117 key_store keys(app);
118
119 if (args.size() > 1)
120 throw usage(execid);
121
122 rsa_keypair_id id;
123 get_user_key(app.opts, app.lua, db, keys, id);
124
125 if (args.empty())
126 keys.export_key_for_agent(id, cout);
127 else
128 {
129 string external_path = system_path(idx(args, 0)).as_external();
130 ofstream fout(external_path.c_str(), ofstream::out);
131 keys.export_key_for_agent(id, fout);
132 }
133}
134
135CMD(ssh_agent_add, "ssh_agent_add", "", CMD_REF(key_and_cert), "",
136 N_("Adds a private key to ssh-agent"),
137 "",
138 options::opts::none)
139{
140 database db(app);
141 key_store keys(app);
142
143 if (args.size() > 1)
144 throw usage(execid);
145
146 rsa_keypair_id id;
147 get_user_key(app.opts, app.lua, db, keys, id);
148 keys.add_key_to_agent(id);
149}
150
151CMD(cert, "cert", "", CMD_REF(key_and_cert),
152 N_("REVISION CERTNAME [CERTVAL]"),
153 N_("Creates a certificate for a revision"),
154 "",
155 options::opts::none)
156{
157 database db(app);
158 key_store keys(app);
159 project_t project(db);
160
161 if ((args.size() != 3) && (args.size() != 2))
162 throw usage(execid);
163
164 transaction_guard guard(db);
165
166 revision_id rid;
167 complete(app.opts, app.lua, project, idx(args, 0)(), rid);
168
169 cert_name cname;
170 internalize_cert_name(idx(args, 1), cname);
171
172 cache_user_key(app.opts, app.lua, db, keys);
173
174 cert_value val;
175 if (args.size() == 3)
176 val = cert_value(idx(args, 2)());
177 else
178 {
179 data dat;
180 read_data_stdin(dat);
181 val = cert_value(dat());
182 }
183
184 project.put_cert(keys, rid, cname, val);
185 guard.commit();
186}
187
188CMD(trusted, "trusted", "", CMD_REF(key_and_cert),
189 N_("REVISION NAME VALUE SIGNER1 [SIGNER2 [...]]"),
190 N_("Tests whether a hypothetical certificate would be trusted"),
191 N_("The current settings are used to run the test."),
192 options::opts::none)
193{
194 database db(app);
195 project_t project(db);
196
197 if (args.size() < 4)
198 throw usage(execid);
199
200 set<revision_id> rids;
201 expand_selector(app.opts, app.lua, project, idx(args, 0)(), rids);
202 diagnose_ambiguous_expansion(project, idx(args, 0)(), rids);
203
204 revision_id ident;
205 if (!rids.empty())
206 ident = *rids.begin();
207
208 cert_name cname;
209 internalize_cert_name(idx(args, 1), cname);
210
211 cert_value value(idx(args, 2)());
212
213 set<rsa_keypair_id> signers;
214 for (unsigned int i = 3; i != args.size(); ++i)
215 {
216 rsa_keypair_id keyid;
217 internalize_rsa_keypair_id(idx(args, i), keyid);
218 signers.insert(keyid);
219 }
220
221
222 bool trusted = app.lua.hook_get_revision_cert_trust(signers, ident,
223 cname, value);
224
225
226 ostringstream all_signers;
227 copy(signers.begin(), signers.end(),
228 ostream_iterator<rsa_keypair_id>(all_signers, " "));
229
230 cout << (F("if a cert on: %s\n"
231 "with key: %s\n"
232 "and value: %s\n"
233 "was signed by: %s\n"
234 "it would be: %s")
235 % ident
236 % cname
237 % value
238 % all_signers.str()
239 % (trusted ? _("trusted") : _("UNtrusted")))
240 << '\n'; // final newline is kept out of the translation
241}
242
243CMD(tag, "tag", "", CMD_REF(review), N_("REVISION TAGNAME"),
244 N_("Puts a symbolic tag certificate on a revision"),
245 "",
246 options::opts::none)
247{
248 database db(app);
249 key_store keys(app);
250 project_t project(db);
251
252 if (args.size() != 2)
253 throw usage(execid);
254
255 revision_id r;
256 complete(app.opts, app.lua, project, idx(args, 0)(), r);
257
258 cache_user_key(app.opts, app.lua, db, keys);
259 project.put_tag(keys, r, idx(args, 1)());
260}
261
262
263CMD(testresult, "testresult", "", CMD_REF(review),
264 N_("ID (pass|fail|true|false|yes|no|1|0)"),
265 N_("Notes the results of running a test on a revision"),
266 "",
267 options::opts::none)
268{
269 database db(app);
270 key_store keys(app);
271 project_t project(db);
272
273 if (args.size() != 2)
274 throw usage(execid);
275
276 revision_id r;
277 complete(app.opts, app.lua, project, idx(args, 0)(), r);
278
279 cache_user_key(app.opts, app.lua, db, keys);
280 cert_revision_testresult(db, keys, r, idx(args, 1)());
281}
282
283
284CMD(approve, "approve", "", CMD_REF(review), N_("REVISION"),
285 N_("Approves a particular revision"),
286 "",
287 options::opts::branch)
288{
289 database db(app);
290 key_store keys(app);
291 project_t project(db);
292
293 if (args.size() != 1)
294 throw usage(execid);
295
296 revision_id r;
297 complete(app.opts, app.lua, project, idx(args, 0)(), r);
298 guess_branch(app.opts, project, r);
299 N(app.opts.branchname() != "", F("need --branch argument for approval"));
300
301 cache_user_key(app.opts, app.lua, db, keys);
302 project.put_revision_in_branch(keys, r, app.opts.branchname);
303}
304
305CMD(suspend, "suspend", "", CMD_REF(review), N_("REVISION"),
306 N_("Suspends a particular revision"),
307 "",
308 options::opts::branch)
309{
310 database db(app);
311 key_store keys(app);
312 project_t project(db);
313
314 if (args.size() != 1)
315 throw usage(execid);
316
317 revision_id r;
318 complete(app.opts, app.lua, project, idx(args, 0)(), r);
319 guess_branch(app.opts, project, r);
320 N(app.opts.branchname() != "", F("need --branch argument to suspend"));
321
322 cache_user_key(app.opts, app.lua, db, keys);
323 project.suspend_revision_in_branch(keys, r, app.opts.branchname);
324}
325
326CMD(comment, "comment", "", CMD_REF(review), N_("REVISION [COMMENT]"),
327 N_("Comments on a particular revision"),
328 "",
329 options::opts::none)
330{
331 database db(app);
332 key_store keys(app);
333 project_t project(db);
334
335 if (args.size() != 1 && args.size() != 2)
336 throw usage(execid);
337
338 utf8 comment;
339 if (args.size() == 2)
340 comment = idx(args, 1);
341 else
342 {
343 external comment_external;
344 N(app.lua.hook_edit_comment(external(""), external(""), comment_external),
345 F("edit comment failed"));
346 system_to_utf8(comment_external, comment);
347 }
348
349 N(comment().find_first_not_of("\n\r\t ") != string::npos,
350 F("empty comment"));
351
352 revision_id r;
353 complete(app.opts, app.lua, project, idx(args, 0)(), r);
354
355 cache_user_key(app.opts, app.lua, db, keys);
356 cert_revision_comment(db, keys, r, comment);
357}
358
359// Local Variables:
360// mode: C++
361// fill-column: 76
362// c-file-style: "gnu"
363// indent-tabs-mode: nil
364// End:
365// 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