aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-10-06 14:10:19 +0000
committerChristian Grothoff <christian@grothoff.org>2013-10-06 14:10:19 +0000
commit4558667c81910199c3dc4e96ab32cd6c6382d2c8 (patch)
tree3b2a399be326c06b2db9e3a3d0251221aa9e3836
parent69cf4d54ba9defa69830d4be84c01940bfb9fe28 (diff)
downloadgnunet-4558667c81910199c3dc4e96ab32cd6c6382d2c8.tar.gz
gnunet-4558667c81910199c3dc4e96ab32cd6c6382d2c8.zip
-first draft for revocation command-line tool
-rw-r--r--src/revocation/Makefile.am1
-rw-r--r--src/revocation/gnunet-revocation.c413
2 files changed, 410 insertions, 4 deletions
diff --git a/src/revocation/Makefile.am b/src/revocation/Makefile.am
index ad603affb..91610b4f0 100644
--- a/src/revocation/Makefile.am
+++ b/src/revocation/Makefile.am
@@ -24,6 +24,7 @@ gnunet_revocation_SOURCES = \
24 gnunet-revocation.c 24 gnunet-revocation.c
25gnunet_revocation_LDADD = \ 25gnunet_revocation_LDADD = \
26 libgnunetrevocation.la \ 26 libgnunetrevocation.la \
27 $(top_builddir)/src/identity/libgnunetidentity.la \
27 $(top_builddir)/src/util/libgnunetutil.la \ 28 $(top_builddir)/src/util/libgnunetutil.la \
28 $(GN_LIBINTL) 29 $(GN_LIBINTL)
29 30
diff --git a/src/revocation/gnunet-revocation.c b/src/revocation/gnunet-revocation.c
index 65b2c9eb9..10259fc99 100644
--- a/src/revocation/gnunet-revocation.c
+++ b/src/revocation/gnunet-revocation.c
@@ -26,6 +26,8 @@
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_util_lib.h" 27#include "gnunet_util_lib.h"
28#include "gnunet_revocation_service.h" 28#include "gnunet_revocation_service.h"
29#include "gnunet_identity_service.h"
30
29 31
30/** 32/**
31 * Final status code. 33 * Final status code.
@@ -33,20 +35,412 @@
33static int ret; 35static int ret;
34 36
35/** 37/**
38 * Was "-p" specified?
39 */
40static int perform;
41
42/**
43 * -f option.
44 */
45static char *filename;
46
47/**
48 * -R option
49 */
50static char *revoke_ego;
51
52/**
53 * -t option.
54 */
55static char *test_ego;
56
57/**
58 * Handle for revocation query.
59 */
60static struct GNUNET_REVOCATION_Query *q;
61
62/**
63 * Handle for revocation.
64 */
65static struct GNUNET_REVOCATION_Handle *h;
66
67/**
68 * Handle for our ego lookup.
69 */
70static struct GNUNET_IDENTITY_EgoLookup *el;
71
72/**
73 * Our configuration.
74 */
75static const struct GNUNET_CONFIGURATION_Handle *cfg;
76
77/**
78 * Number of matching bits required for revocation.
79 */
80static unsigned long long matching_bits;
81
82
83/**
84 * Function run if the user aborts with CTRL-C.
85 *
86 * @param cls closure
87 * @param tc scheduler context
88 */
89static void
90do_shutdown (void *cls,
91 const struct GNUNET_SCHEDULER_TaskContext *tc)
92{
93 if (NULL != q)
94 {
95 GNUNET_REVOCATION_query_cancel (q);
96 q = NULL;
97 }
98 if (NULL != h)
99 {
100 GNUNET_REVOCATION_revoke_cancel (h);
101 h = NULL;
102 }
103}
104
105
106/**
107 * Print the result from a revocation query.
108 *
109 * @param cls NULL
110 * @param is_valid #GNUNET_YES if the key is still valid, #GNUNET_NO if not, #GNUNET_SYSERR on error
111 */
112static void
113print_query_result (void *cls,
114 int is_valid)
115{
116 q = NULL;
117 switch (is_valid)
118 {
119 case GNUNET_YES:
120 FPRINTF (stdout,
121 _("Key `%s' is valid\n"),
122 test_ego);
123 break;
124 case GNUNET_NO:
125 FPRINTF (stdout,
126 _("Key `%s' has been revoked\n"),
127 test_ego);
128 break;
129 case GNUNET_SYSERR:
130 FPRINTF (stdout,
131 "%s",
132 _("Internal error\n"));
133 break;
134 default:
135 GNUNET_break (0);
136 break;
137 }
138 GNUNET_SCHEDULER_shutdown ();
139}
140
141
142/**
143 * Print the result from a revocation request.
144 *
145 * @param cls NULL
146 * @param is_valid #GNUNET_YES if the key is still valid, #GNUNET_NO if not, #GNUNET_SYSERR on error
147 */
148static void
149print_revocation_result (void *cls,
150 int is_valid)
151{
152 h = NULL;
153 switch (is_valid)
154 {
155 case GNUNET_YES:
156 FPRINTF (stdout,
157 _("Key for ego `%s' is still valid, revocation failed (!)\n"),
158 test_ego);
159 break;
160 case GNUNET_NO:
161 FPRINTF (stdout,
162 _("Key for ego `%s' has been successfully revoked\n"),
163 test_ego);
164 break;
165 case GNUNET_SYSERR:
166 FPRINTF (stdout,
167 "%s",
168 _("Internal error, key revocation might have failed\n"));
169 break;
170 default:
171 GNUNET_break (0);
172 break;
173 }
174 GNUNET_SCHEDULER_shutdown ();
175}
176
177
178/**
179 * Data needed to perform a revocation.
180 */
181struct RevocationData
182{
183 /**
184 * Public key.
185 */
186 struct GNUNET_CRYPTO_EccPublicSignKey key;
187
188 /**
189 * Revocation signature data.
190 */
191 struct GNUNET_CRYPTO_EccSignature sig;
192
193 /**
194 * Proof of work (in NBO).
195 */
196 uint64_t pow GNUNET_PACKED;
197};
198
199
200/**
201 * Perform the revocation.
202 */
203static void
204perform_revocation (const struct RevocationData *rd)
205{
206 h = GNUNET_REVOCATION_revoke (cfg,
207 &rd->key,
208 &rd->sig,
209 rd->pow,
210 &print_revocation_result,
211 NULL);
212}
213
214
215/**
216 * Perform the proof-of-work calculation.
217 *
218 * @param cls the `struct RevocationData`
219 * @param tc scheduler context
220 */
221static void
222calculate_pow (void *cls,
223 const struct GNUNET_SCHEDULER_TaskContext *tc)
224{
225 struct RevocationData *rd = cls;
226
227 if ( (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) ||
228 (0 == (rd->pow % 128) ) )
229 {
230 if (0 == (rd->pow % 128 * 1024))
231 {
232 if (0 == (rd->pow % (1024 * 128 * 80)))
233 fprintf (stderr, "\n");
234 fprintf (stderr, ".");
235 }
236 if ( (NULL != filename) &&
237 (sizeof (struct RevocationData) ==
238 GNUNET_DISK_fn_write (filename,
239 &rd,
240 sizeof (rd),
241 GNUNET_DISK_PERM_USER_READ |
242 GNUNET_DISK_PERM_USER_WRITE)) )
243 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
244 "write",
245 filename);
246 }
247 if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
248 {
249 GNUNET_free (rd);
250 return;
251 }
252 rd->pow++;
253 if (GNUNET_OK ==
254 GNUNET_REVOCATION_check_pow (&rd->key,
255 rd->pow,
256 (unsigned int) matching_bits))
257 {
258 if ( (NULL != filename) &&
259 (sizeof (struct RevocationData) ==
260 GNUNET_DISK_fn_write (filename,
261 &rd,
262 sizeof (rd),
263 GNUNET_DISK_PERM_USER_READ |
264 GNUNET_DISK_PERM_USER_WRITE)) )
265 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
266 "write",
267 filename);
268 if (perform)
269 perform_revocation (rd);
270 else
271 {
272 FPRINTF (stderr,
273 _("Revocation certificate for `%s' stored in `%s'\n"),
274 revoke_ego,
275 filename);
276 GNUNET_SCHEDULER_shutdown ();
277 }
278 GNUNET_free (rd);
279 }
280 GNUNET_SCHEDULER_add_now (&calculate_pow,
281 rd);
282}
283
284
285/**
286 * Function called with the result from the ego lookup.
287 *
288 * @param cls closure
289 * @param ego the ego, NULL if not found
290 */
291static void
292ego_callback (void *cls,
293 const struct GNUNET_IDENTITY_Ego *ego)
294{
295 struct RevocationData *rd;
296 struct GNUNET_CRYPTO_EccPublicSignKey key;
297
298 el = NULL;
299 if (NULL == ego)
300 {
301 FPRINTF (stdout,
302 _("Ego `%s' not found.\n"),
303 test_ego);
304 GNUNET_SCHEDULER_shutdown ();
305 return;
306 }
307 GNUNET_IDENTITY_ego_get_public_key (ego,
308 &key);
309 rd = GNUNET_new (struct RevocationData);
310 if ( (NULL != filename) &&
311 (GNUNET_YES ==
312 GNUNET_DISK_file_test (filename)) &&
313 (sizeof (struct RevocationData) ==
314 GNUNET_DISK_fn_read (filename,
315 &rd,
316 sizeof (rd))) )
317 {
318 if (0 != memcmp (&rd->key,
319 &key,
320 sizeof (struct GNUNET_CRYPTO_EccPublicSignKey)))
321 {
322 fprintf (stderr,
323 _("Error: revocation certificate in `%s' is not for `%s'\n"),
324 filename,
325 revoke_ego);
326 GNUNET_free (rd);
327 return;
328 }
329 }
330 else
331 {
332 GNUNET_REVOCATION_sign_revocation (GNUNET_IDENTITY_ego_get_private_key (ego),
333 &rd->sig);
334 rd->key = key;
335 }
336 if (GNUNET_YES ==
337 GNUNET_REVOCATION_check_pow (&key,
338 rd->pow,
339 (unsigned int) matching_bits))
340 {
341 FPRINTF (stderr,
342 "%s",
343 _("Revocation certificate ready, initiating revocation\n"));
344 perform_revocation (rd);
345 GNUNET_free (rd);
346 return;
347 }
348 FPRINTF (stderr,
349 "%s",
350 _("Revocation certificate not ready, calculating proof of work\n"));
351 GNUNET_SCHEDULER_add_now (&calculate_pow,
352 rd);
353}
354
355
356/**
36 * Main function that will be run by the scheduler. 357 * Main function that will be run by the scheduler.
37 * 358 *
38 * @param cls closure 359 * @param cls closure
39 * @param args remaining command-line arguments 360 * @param args remaining command-line arguments
40 * @param cfgfile name of the configuration file used (for saving, can be NULL!) 361 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
41 * @param cfg configuration 362 * @param c configuration
42 */ 363 */
43static void 364static void
44run (void *cls, 365run (void *cls,
45 char *const *args, 366 char *const *args,
46 const char *cfgfile, 367 const char *cfgfile,
47 const struct GNUNET_CONFIGURATION_Handle *cfg) 368 const struct GNUNET_CONFIGURATION_Handle *c)
48{ 369{
49 /* main code here */ 370 struct GNUNET_CRYPTO_EccPublicSignKey pk;
371 struct RevocationData rd;
372
373 cfg = c;
374 if (NULL != test_ego)
375 {
376 if (GNUNET_OK !=
377 GNUNET_CRYPTO_ecc_public_sign_key_from_string (test_ego,
378 strlen (test_ego),
379 &pk))
380 {
381 FPRINTF (stderr,
382 _("Public key `%s' malformed\n"),
383 test_ego);
384 return;
385 }
386 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
387 &do_shutdown,
388 NULL);
389 q = GNUNET_REVOCATION_query (cfg,
390 &pk,
391 &print_query_result,
392 NULL);
393 if (NULL != revoke_ego)
394 FPRINTF (stderr,
395 "%s",
396 _("Testing and revoking at the same time is not allowed, only executing test.\n"));
397 return;
398 }
399 if (GNUNET_OK !=
400 GNUNET_CONFIGURATION_get_value_number (cfg,
401 "REVOCATION",
402 "WORKBITS",
403 &matching_bits))
404 {
405 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
406 "REVOCATION",
407 "WORKBITS");
408 return;
409 }
410 if (NULL != revoke_ego)
411 {
412 /* main code here */
413 el = GNUNET_IDENTITY_ego_lookup (cfg,
414 revoke_ego,
415 &ego_callback,
416 NULL);
417 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
418 &do_shutdown,
419 NULL);
420 return;
421 }
422 if ( (NULL != filename) &&
423 (perform) )
424 {
425 if (sizeof (rd) !=
426 GNUNET_DISK_fn_read (filename,
427 &rd,
428 sizeof (rd)))
429 {
430 fprintf (stderr,
431 _("Failed to read revocation certificate from `%s'\n"),
432 filename);
433 return;
434 }
435 perform_revocation (&rd);
436 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
437 &do_shutdown,
438 NULL);
439 return;
440 }
441 FPRINTF (stderr,
442 "%s",
443 _("No action specified. Nothing to do.\n"));
50} 444}
51 445
52 446
@@ -61,7 +455,18 @@ int
61main (int argc, char *const *argv) 455main (int argc, char *const *argv)
62{ 456{
63 static const struct GNUNET_GETOPT_CommandLineOption options[] = { 457 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
64 /* FIMXE: add options here */ 458 {'f', "filename", "NAME",
459 gettext_noop ("use NAME for the name of the revocation file"),
460 1, &GNUNET_GETOPT_set_string, &filename},
461 {'R', "revoke", "NAME",
462 gettext_noop ("revoke the private key associated with the ego NAME "),
463 1, &GNUNET_GETOPT_set_string, &revoke_ego},
464 {'p', "perform", NULL,
465 gettext_noop ("actually perform the revocation revocation file, otherwise we just do the precomputation"),
466 0, &GNUNET_GETOPT_set_one, &perform},
467 {'t', "test", "KEY",
468 gettext_noop ("test if the public key KEY has been revoked"),
469 1, &GNUNET_GETOPT_set_string, &test_ego},
65 GNUNET_GETOPT_OPTION_END 470 GNUNET_GETOPT_OPTION_END
66 }; 471 };
67 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) 472 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))