diff options
-rw-r--r-- | src/revocation/Makefile.am | 1 | ||||
-rw-r--r-- | src/revocation/gnunet-revocation.c | 413 |
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 |
25 | gnunet_revocation_LDADD = \ | 25 | gnunet_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 @@ | |||
33 | static int ret; | 35 | static int ret; |
34 | 36 | ||
35 | /** | 37 | /** |
38 | * Was "-p" specified? | ||
39 | */ | ||
40 | static int perform; | ||
41 | |||
42 | /** | ||
43 | * -f option. | ||
44 | */ | ||
45 | static char *filename; | ||
46 | |||
47 | /** | ||
48 | * -R option | ||
49 | */ | ||
50 | static char *revoke_ego; | ||
51 | |||
52 | /** | ||
53 | * -t option. | ||
54 | */ | ||
55 | static char *test_ego; | ||
56 | |||
57 | /** | ||
58 | * Handle for revocation query. | ||
59 | */ | ||
60 | static struct GNUNET_REVOCATION_Query *q; | ||
61 | |||
62 | /** | ||
63 | * Handle for revocation. | ||
64 | */ | ||
65 | static struct GNUNET_REVOCATION_Handle *h; | ||
66 | |||
67 | /** | ||
68 | * Handle for our ego lookup. | ||
69 | */ | ||
70 | static struct GNUNET_IDENTITY_EgoLookup *el; | ||
71 | |||
72 | /** | ||
73 | * Our configuration. | ||
74 | */ | ||
75 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
76 | |||
77 | /** | ||
78 | * Number of matching bits required for revocation. | ||
79 | */ | ||
80 | static 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 | */ | ||
89 | static void | ||
90 | do_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 | */ | ||
112 | static void | ||
113 | print_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 | */ | ||
148 | static void | ||
149 | print_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 | */ | ||
181 | struct 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 | */ | ||
203 | static void | ||
204 | perform_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 | */ | ||
221 | static void | ||
222 | calculate_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 | */ | ||
291 | static void | ||
292 | ego_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 | */ |
43 | static void | 364 | static void |
44 | run (void *cls, | 365 | run (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 | |||
61 | main (int argc, char *const *argv) | 455 | main (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)) |