GNUnet  0.10.x
gnunet-revocation.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2013 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
30 
31 
35 static int ret;
36 
40 static int perform;
41 
45 static char *filename;
46 
50 static char *revoke_ego;
51 
55 static char *test_ego;
56 
60 static struct GNUNET_REVOCATION_Query *q;
61 
65 static struct GNUNET_REVOCATION_Handle *h;
66 
71 
75 static const struct GNUNET_CONFIGURATION_Handle *cfg;
76 
80 static unsigned long long matching_bits;
81 
86 
87 
93 static void
94 do_shutdown(void *cls)
95 {
96  if (NULL != el)
97  {
99  el = NULL;
100  }
101  if (NULL != q)
102  {
104  q = NULL;
105  }
106  if (NULL != h)
107  {
109  h = NULL;
110  }
111 }
112 
113 
120 static void
121 print_query_result(void *cls, int is_valid)
122 {
123  q = NULL;
124  switch (is_valid)
125  {
126  case GNUNET_YES:
127  fprintf(stdout, _("Key `%s' is valid\n"), test_ego);
128  break;
129 
130  case GNUNET_NO:
131  fprintf(stdout, _("Key `%s' has been revoked\n"), test_ego);
132  break;
133 
134  case GNUNET_SYSERR:
135  fprintf(stdout, "%s", _("Internal error\n"));
136  break;
137 
138  default:
139  GNUNET_break(0);
140  break;
141  }
143 }
144 
145 
152 static void
153 print_revocation_result(void *cls, int is_valid)
154 {
155  h = NULL;
156  switch (is_valid)
157  {
158  case GNUNET_YES:
159  if (NULL != revoke_ego)
160  fprintf(stdout,
161  _("Key for ego `%s' is still valid, revocation failed (!)\n"),
162  revoke_ego);
163  else
164  fprintf(stdout, "%s", _("Revocation failed (!)\n"));
165  break;
166 
167  case GNUNET_NO:
168  if (NULL != revoke_ego)
169  fprintf(stdout,
170  _("Key for ego `%s' has been successfully revoked\n"),
171  revoke_ego);
172  else
173  fprintf(stdout, "%s", _("Revocation successful.\n"));
174  break;
175 
176  case GNUNET_SYSERR:
177  fprintf(stdout,
178  "%s",
179  _("Internal error, key revocation might have failed\n"));
180  break;
181 
182  default:
183  GNUNET_break(0);
184  break;
185  }
187 }
188 
189 
198 
203 
207  uint64_t pow GNUNET_PACKED;
208 };
209 
210 
214 static void
216 {
217  h = GNUNET_REVOCATION_revoke(cfg,
218  &rd->key,
219  &rd->sig,
220  rd->pow,
222  NULL);
223 }
224 
225 
232 static void
233 sync_rd(const struct RevocationData *rd)
234 {
235  if ((NULL != filename) &&
236  (sizeof(struct RevocationData) ==
238  &rd,
239  sizeof(rd),
243 }
244 
245 
251 static void
253 {
254  struct RevocationData *rd = cls;
255 
256  if (NULL != pow_task)
257  {
258  GNUNET_SCHEDULER_cancel(pow_task);
259  pow_task = NULL;
260  }
261  sync_rd(rd);
262  GNUNET_free(rd);
263 }
264 
265 
271 static void
272 calculate_pow(void *cls)
273 {
274  struct RevocationData *rd = cls;
275 
276  /* store temporary results */
277  pow_task = NULL;
278  if (0 == (rd->pow % 128))
279  sync_rd(rd);
280  /* display progress estimate */
281  if ((0 == ((1 << matching_bits) / 100 / 50)) ||
282  (0 == (rd->pow % ((1 << matching_bits) / 100 / 50))))
283  fprintf(stderr, "%s", ".");
284  if ((0 != rd->pow) && ((0 == ((1 << matching_bits) / 100)) ||
285  (0 == (rd->pow % ((1 << matching_bits) / 100)))))
286  fprintf(stderr,
287  " - @ %3u%% (estimate)\n",
288  (unsigned int)(rd->pow * 100) / (1 << matching_bits));
289  /* actually do POW calculation */
290  rd->pow++;
292  rd->pow,
293  (unsigned int)matching_bits))
294  {
295  if ((NULL != filename) &&
296  (sizeof(struct RevocationData) !=
298  rd,
299  sizeof(struct RevocationData),
303  if (perform)
304  {
305  perform_revocation(rd);
306  }
307  else
308  {
309  fprintf(stderr, "%s", "\n");
310  fprintf(stderr,
311  _("Revocation certificate for `%s' stored in `%s'\n"),
312  revoke_ego,
313  filename);
315  }
316  return;
317  }
318  pow_task = GNUNET_SCHEDULER_add_now(&calculate_pow, rd);
319 }
320 
321 
328 static void
329 ego_callback(void *cls, const struct GNUNET_IDENTITY_Ego *ego)
330 {
331  struct RevocationData *rd;
332  struct GNUNET_CRYPTO_EcdsaPublicKey key;
333 
334  el = NULL;
335  if (NULL == ego)
336  {
337  fprintf(stdout, _("Ego `%s' not found.\n"), revoke_ego);
339  return;
340  }
342  rd = GNUNET_new(struct RevocationData);
343  if ((NULL != filename) && (GNUNET_YES == GNUNET_DISK_file_test(filename)) &&
344  (sizeof(struct RevocationData) ==
345  GNUNET_DISK_fn_read(filename, rd, sizeof(struct RevocationData))))
346  {
347  if (0 != GNUNET_memcmp(&rd->key, &key))
348  {
349  fprintf(stderr,
350  _("Error: revocation certificate in `%s' is not for `%s'\n"),
351  filename,
352  revoke_ego);
353  GNUNET_free(rd);
354  return;
355  }
356  }
357  else
358  {
360  ego),
361  &rd->sig);
362  rd->key = key;
363  }
364  if (GNUNET_YES ==
365  GNUNET_REVOCATION_check_pow(&key, rd->pow, (unsigned int)matching_bits))
366  {
367  fprintf(stderr, "%s", _("Revocation certificate ready\n"));
368  if (perform)
369  perform_revocation(rd);
370  else
372  GNUNET_free(rd);
373  return;
374  }
375  fprintf(stderr,
376  "%s",
377  _("Revocation certificate not ready, calculating proof of work\n"));
378  pow_task = GNUNET_SCHEDULER_add_now(&calculate_pow, rd);
380 }
381 
382 
391 static void
392 run(void *cls,
393  char *const *args,
394  const char *cfgfile,
395  const struct GNUNET_CONFIGURATION_Handle *c)
396 {
398  struct RevocationData rd;
399 
400  cfg = c;
401  if (NULL != test_ego)
402  {
403  if (GNUNET_OK !=
405  strlen(test_ego),
406  &pk))
407  {
408  fprintf(stderr, _("Public key `%s' malformed\n"), test_ego);
409  return;
410  }
412  q = GNUNET_REVOCATION_query(cfg, &pk, &print_query_result, NULL);
413  if (NULL != revoke_ego)
414  fprintf(
415  stderr,
416  "%s",
417  _(
418  "Testing and revoking at the same time is not allowed, only executing test.\n"));
419  return;
420  }
422  "REVOCATION",
423  "WORKBITS",
424  &matching_bits))
425  {
427  "REVOCATION",
428  "WORKBITS");
429  return;
430  }
431  if (NULL != revoke_ego)
432  {
433  if (!perform && (NULL == filename))
434  {
435  fprintf(stderr,
436  "%s",
437  _("No filename to store revocation certificate given.\n"));
438  return;
439  }
440  /* main code here */
443  return;
444  }
445  if ((NULL != filename) && (perform))
446  {
447  if (sizeof(rd) != GNUNET_DISK_fn_read(filename, &rd, sizeof(rd)))
448  {
449  fprintf(stderr,
450  _("Failed to read revocation certificate from `%s'\n"),
451  filename);
452  return;
453  }
455  if (GNUNET_YES !=
457  rd.pow,
458  (unsigned int)matching_bits))
459  {
460  struct RevocationData *cp = GNUNET_new(struct RevocationData);
461 
462  *cp = rd;
463  pow_task = GNUNET_SCHEDULER_add_now(&calculate_pow, cp);
465  return;
466  }
467  perform_revocation(&rd);
468  return;
469  }
470  fprintf(stderr, "%s", _("No action specified. Nothing to do.\n"));
471 }
472 
473 
481 int
482 main(int argc, char *const *argv)
483 {
484  struct GNUNET_GETOPT_CommandLineOption options[] = {
486  "filename",
487  "NAME",
488  gettext_noop(
489  "use NAME for the name of the revocation file"),
490  &filename),
491 
493  'R',
494  "revoke",
495  "NAME",
496  gettext_noop(
497  "revoke the private key associated for the the private key associated with the ego NAME "),
498  &revoke_ego),
499 
501  'p',
502  "perform",
503  gettext_noop(
504  "actually perform revocation, otherwise we just do the precomputation"),
505  &perform),
506 
508  "test",
509  "KEY",
510  gettext_noop(
511  "test if the public key KEY has been revoked"),
512  &test_ego),
513 
515  };
516 
517  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args(argc, argv, &argc, &argv))
518  return 2;
519 
520  ret = (GNUNET_OK == GNUNET_PROGRAM_run(argc,
521  argv,
522  "gnunet-revocation",
523  gettext_noop("help text"),
524  options,
525  &run,
526  NULL))
527  ? ret
528  : 1;
529  GNUNET_free((void *)argv);
530  return ret;
531 }
532 
533 /* end of gnunet-revocation.c */
int GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory)...
Definition: disk.c:541
static struct GNUNET_IDENTITY_EgoLookup * el
Handle for our ego lookup.
static void sync_rd(const struct RevocationData *rd)
Write the current state of the revocation data to disk.
void GNUNET_REVOCATION_query_cancel(struct GNUNET_REVOCATION_Query *q)
Cancel key revocation check.
void GNUNET_IDENTITY_ego_lookup_cancel(struct GNUNET_IDENTITY_EgoLookup *el)
Abort ego lookup attempt.
Handle for ego lookup.
int GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
struct GNUNET_REVOCATION_Handle * GNUNET_REVOCATION_revoke(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_EcdsaPublicKey *key, const struct GNUNET_CRYPTO_EcdsaSignature *sig, uint64_t pow, GNUNET_REVOCATION_Callback func, void *func_cls)
Perform key revocation.
static char * filename
-f option.
static int ret
Final status code.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1284
void GNUNET_REVOCATION_sign_revocation(const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, struct GNUNET_CRYPTO_EcdsaSignature *sig)
Create a revocation signature.
int GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1439
static void ego_callback(void *cls, const struct GNUNET_IDENTITY_Ego *ego)
Function called with the result from the ego lookup.
const struct GNUNET_CRYPTO_EcdsaPrivateKey * GNUNET_IDENTITY_ego_get_private_key(const struct GNUNET_IDENTITY_Ego *ego)
Obtain the ECC key associated with a ego.
Definition: identity_api.c:553
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
struct GNUNET_CRYPTO_EcdsaPublicKey key
Public key.
int main(int argc, char *const *argv)
The main function of gnunet-revocation.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
Definition of a command line option.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:517
static void print_query_result(void *cls, int is_valid)
Print the result from a revocation query.
static struct GNUNET_SCHEDULER_Task * pow_task
Task used for proof-of-work calculation.
ssize_t GNUNET_DISK_fn_write(const char *fn, const void *buffer, size_t n, enum GNUNET_DISK_AccessPermissions mode)
Write a buffer to a file.
Definition: disk.c:877
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
Main function that will be run by the scheduler.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_string(char shortName, const char *name, const char *argumentHelp, const char *description, char **str)
Allow user to specify a string.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
Handle for an ego.
Definition: identity.h:237
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
static void calculate_pow_shutdown(void *cls)
Perform the proof-of-work calculation.
static struct GNUNET_REVOCATION_Handle * h
Handle for revocation.
static void calculate_pow(void *cls)
Perform the proof-of-work calculation.
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1264
an ECC signature using ECDSA
static int perform
Was "-p" specified?
Data needed to perform a revocation.
static void do_shutdown(void *cls)
Function run if the user aborts with CTRL-C.
static struct GNUNET_REVOCATION_Query * q
Handle for revocation query.
static char * test_ego
-t option.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
Handle for the key revocation query.
void GNUNET_IDENTITY_ego_get_public_key(const struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_CRYPTO_EcdsaPublicKey *pk)
Get the identifier (public key) of an ego.
Definition: identity_api.c:566
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
uint64_t pow
Proof of work (in NBO).
struct GNUNET_IDENTITY_EgoLookup * GNUNET_IDENTITY_ego_lookup(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *name, GNUNET_IDENTITY_EgoCallback cb, void *cb_cls)
Lookup an ego by name.
int GNUNET_CRYPTO_ecdsa_public_key_from_string(const char *enc, size_t enclen, struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
Convert a string representing a public key to a public key.
Definition: crypto_ecc.c:468
#define GNUNET_PACKED
gcc-ism to get packed structs.
static char * revoke_ego
-R option
configuration data
Definition: configuration.c:83
static void print_revocation_result(void *cls, int is_valid)
Print the result from a revocation request.
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_flag(char shortName, const char *name, const char *description, int *val)
Allow user to specify a flag (which internally means setting an integer to 1/GNUNET_YES/GNUNET_OK.
struct GNUNET_CRYPTO_EcdsaSignature sig
Revocation signature data.
Entry in list of pending tasks.
Definition: scheduler.c:131
struct GNUNET_REVOCATION_Query * GNUNET_REVOCATION_query(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_EcdsaPublicKey *key, GNUNET_REVOCATION_Callback func, void *func_cls)
Check if a key was revoked.
Handle for the key revocation operation.
int GNUNET_PROGRAM_run(int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration, parse options).
Definition: program.c:367
static void perform_revocation(const struct RevocationData *rd)
Perform the revocation.
#define GNUNET_YES
Definition: gnunet_common.h:77
void GNUNET_REVOCATION_revoke_cancel(struct GNUNET_REVOCATION_Handle *h)
Cancel key revocation.
static unsigned long long matching_bits
Number of matching bits required for revocation.
ssize_t GNUNET_DISK_fn_read(const char *fn, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:791
#define GNUNET_free(ptr)
Wrapper around free.
#define gettext_noop(String)
Definition: gettext.h:69
int GNUNET_REVOCATION_check_pow(const struct GNUNET_CRYPTO_EcdsaPublicKey *key, uint64_t pow, unsigned int matching_bits)
Check if the given proof-of-work value would be acceptable for revoking the given key...
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956