GNUnet  0.11.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 
34 static unsigned int pow_passes = 1;
35 
39 static int ret;
40 
44 static int perform;
45 
49 static char *filename;
50 
54 static char *revoke_ego;
55 
59 static char *test_ego;
60 
64 static unsigned int epochs = 1;
65 
69 static struct GNUNET_REVOCATION_Query *q;
70 
74 static struct GNUNET_REVOCATION_Handle *h;
75 
80 
84 static const struct GNUNET_CONFIGURATION_Handle *cfg;
85 
89 static unsigned long long matching_bits;
90 
95 
100 
105 
111 static void
112 do_shutdown (void *cls)
113 {
114  fprintf (stderr, "%s", _ ("Shutting down...\n"));
115  if (NULL != el)
116  {
118  el = NULL;
119  }
120  if (NULL != q)
121  {
123  q = NULL;
124  }
125  if (NULL != h)
126  {
128  h = NULL;
129  }
130 }
131 
132 
139 static void
140 print_query_result (void *cls, int is_valid)
141 {
142  q = NULL;
143  switch (is_valid)
144  {
145  case GNUNET_YES:
146  fprintf (stdout, _ ("Key `%s' is valid\n"), test_ego);
147  break;
148 
149  case GNUNET_NO:
150  fprintf (stdout, _ ("Key `%s' has been revoked\n"), test_ego);
151  break;
152 
153  case GNUNET_SYSERR:
154  fprintf (stdout, "%s", _ ("Internal error\n"));
155  break;
156 
157  default:
158  GNUNET_break (0);
159  break;
160  }
162 }
163 
164 
171 static void
172 print_revocation_result (void *cls, int is_valid)
173 {
174  h = NULL;
175  switch (is_valid)
176  {
177  case GNUNET_YES:
178  if (NULL != revoke_ego)
179  fprintf (stdout,
180  _ ("Key for ego `%s' is still valid, revocation failed (!)\n"),
181  revoke_ego);
182  else
183  fprintf (stdout, "%s", _ ("Revocation failed (!)\n"));
184  break;
185 
186  case GNUNET_NO:
187  if (NULL != revoke_ego)
188  fprintf (stdout,
189  _ ("Key for ego `%s' has been successfully revoked\n"),
190  revoke_ego);
191  else
192  fprintf (stdout, "%s", _ ("Revocation successful.\n"));
193  break;
194 
195  case GNUNET_SYSERR:
196  fprintf (stdout,
197  "%s",
198  _ ("Internal error, key revocation might have failed\n"));
199  break;
200 
201  default:
202  GNUNET_break (0);
203  break;
204  }
206 }
207 
208 
212 static void
214 {
215  h = GNUNET_REVOCATION_revoke (cfg,
216  proof_of_work,
218  NULL);
219 }
220 
221 
228 static void
230 {
231  size_t psize = GNUNET_REVOCATION_proof_get_size (proof_of_work);
232  if ((NULL != filename) &&
233  (GNUNET_OK !=
235  proof_of_work,
236  psize,
240 }
241 
242 
248 static void
250 {
252  fprintf (stderr, "%s", _ ("Cancelling calculation.\n"));
253  sync_pow ();
254  if (NULL != pow_task)
255  {
256  GNUNET_SCHEDULER_cancel (pow_task);
257  pow_task = NULL;
258  }
259  if (NULL != ph)
261 }
262 
263 
269 static void
270 calculate_pow (void *cls)
271 {
273  size_t psize;
274 
275  /* store temporary results */
276  pow_task = NULL;
277  if (0 == (pow_passes % 128))
278  sync_pow ();
279  /* actually do POW calculation */
281  {
282  psize = GNUNET_REVOCATION_proof_get_size (proof_of_work);
283  if (NULL != filename)
284  {
286  if (GNUNET_OK !=
288  proof_of_work,
289  psize,
293  }
294  if (perform)
295  {
297  }
298  else
299  {
300  fprintf (stderr, "%s", "\n");
301  fprintf (stderr,
302  _ ("Revocation certificate for `%s' stored in `%s'\n"),
303  revoke_ego,
304  filename);
306  }
307  return;
308  }
309  pow_passes++;
313  if (0 == pow_passes % 128)
315  &calculate_pow,
316  ph);
317  else
319  &calculate_pow,
320  ph);
321 
322 }
323 
324 
331 static void
332 ego_callback (void *cls, struct GNUNET_IDENTITY_Ego *ego)
333 {
334  struct GNUNET_IDENTITY_PublicKey key;
335  const struct GNUNET_IDENTITY_PrivateKey *privkey;
337  size_t psize;
338 
339  el = NULL;
340  if (NULL == ego)
341  {
342  fprintf (stdout, _ ("Ego `%s' not found.\n"), revoke_ego);
344  return;
345  }
347  privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
349  if ((NULL != filename) && (GNUNET_YES == GNUNET_DISK_file_test (filename)) &&
350  (0 < (psize =
351  GNUNET_DISK_fn_read (filename, proof_of_work,
353  {
354  size_t ksize = GNUNET_IDENTITY_key_get_length (&key);
355  if (((psize - sizeof (*proof_of_work)) < ksize) || // Key too small
356  (0 != memcmp (&proof_of_work[1], &key, ksize))) // Keys do not match
357  {
358  fprintf (stderr,
359  _ ("Error: revocation certificate in `%s' is not for `%s'\n"),
360  filename,
361  revoke_ego);
362  return;
363  }
364  if (GNUNET_YES ==
365  GNUNET_REVOCATION_check_pow (proof_of_work,
366  (unsigned int) matching_bits,
368  {
369  fprintf (stderr, "%s", _ ("Revocation certificate ready\n"));
370  if (perform)
372  else
374  return;
375  }
379  fprintf (stderr,
380  "%s",
381  _ ("Continuing calculation where left off...\n"));
382  ph = GNUNET_REVOCATION_pow_start (proof_of_work,
383  epochs,
384  matching_bits);
385  }
386  fprintf (stderr,
387  "%s",
388  _ ("Revocation certificate not ready, calculating proof of work\n"));
389  if (NULL == ph)
390  {
392  proof_of_work);
393  ph = GNUNET_REVOCATION_pow_start (proof_of_work,
394  epochs, /* Epochs */
395  matching_bits);
396  }
397  pow_task = GNUNET_SCHEDULER_add_now (&calculate_pow, ph);
399 }
400 
401 
410 static void
411 run (void *cls,
412  char *const *args,
413  const char *cfgfile,
414  const struct GNUNET_CONFIGURATION_Handle *c)
415 {
416  struct GNUNET_IDENTITY_PublicKey pk;
417  size_t psize;
418 
419  cfg = c;
420  if (NULL != test_ego)
421  {
422  if (GNUNET_OK !=
424  &pk))
425  {
426  fprintf (stderr, _ ("Public key `%s' malformed\n"), test_ego);
427  return;
428  }
430  q = GNUNET_REVOCATION_query (cfg, &pk, &print_query_result, NULL);
431  if (NULL != revoke_ego)
432  fprintf (
433  stderr,
434  "%s",
435  _ (
436  "Testing and revoking at the same time is not allowed, only executing test.\n"));
437  return;
438  }
440  "REVOCATION",
441  "WORKBITS",
442  &matching_bits))
443  {
445  "REVOCATION",
446  "WORKBITS");
447  return;
448  }
450  "REVOCATION",
451  "EPOCH_DURATION",
452  &epoch_duration))
453  {
455  "REVOCATION",
456  "EPOCH_DURATION");
457  return;
458  }
459 
460  if (NULL != revoke_ego)
461  {
462  if (! perform && (NULL == filename))
463  {
464  fprintf (stderr,
465  "%s",
466  _ ("No filename to store revocation certificate given.\n"));
467  return;
468  }
469  /* main code here */
472  return;
473  }
474  if ((NULL != filename) && (perform))
475  {
476  size_t bread;
478  if (0 < (bread = GNUNET_DISK_fn_read (filename,
479  proof_of_work,
481  {
482  fprintf (stderr,
483  _ ("Failed to read revocation certificate from `%s'\n"),
484  filename);
485  return;
486  }
487  psize = GNUNET_REVOCATION_proof_get_size (proof_of_work);
488  if (bread != psize)
489  {
490  fprintf (stderr,
491  _ ("Revocation certificate corrupted in `%s'\n"),
492  filename);
493  return;
494  }
496  if (GNUNET_YES !=
497  GNUNET_REVOCATION_check_pow (proof_of_work,
498  (unsigned int) matching_bits,
500  {
502  ph = GNUNET_REVOCATION_pow_start (proof_of_work,
503  epochs, /* Epochs */
504  matching_bits);
505 
506  pow_task = GNUNET_SCHEDULER_add_now (&calculate_pow, ph);
508  return;
509  }
511  return;
512  }
513  fprintf (stderr, "%s", _ ("No action specified. Nothing to do.\n"));
514 }
515 
516 
524 int
525 main (int argc, char *const *argv)
526 {
527  struct GNUNET_GETOPT_CommandLineOption options[] = {
529  "filename",
530  "NAME",
531  gettext_noop (
532  "use NAME for the name of the revocation file"),
533  &filename),
534 
536  'R',
537  "revoke",
538  "NAME",
539  gettext_noop (
540  "revoke the private key associated for the the private key associated with the ego NAME "),
541  &revoke_ego),
542 
544  'p',
545  "perform",
546  gettext_noop (
547  "actually perform revocation, otherwise we just do the precomputation"),
548  &perform),
549 
551  "test",
552  "KEY",
553  gettext_noop (
554  "test if the public key KEY has been revoked"),
555  &test_ego),
557  "epochs",
558  "EPOCHS",
559  gettext_noop (
560  "number of epochs to calculate for"),
561  &epochs),
562 
564  };
565 
566  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
567  return 2;
568 
569  ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc,
570  argv,
571  "gnunet-revocation",
572  gettext_noop ("help text"),
573  options,
574  &run,
575  NULL))
576  ? ret
577  : 1;
578  GNUNET_free_nz ((void *) argv);
579  return ret;
580 }
581 
582 
583 /* end of gnunet-revocation.c */
static unsigned int epochs
-e option.
static struct GNUNET_IDENTITY_EgoLookup * el
Handle for our ego lookup.
void GNUNET_REVOCATION_query_cancel(struct GNUNET_REVOCATION_Query *q)
Cancel key revocation check.
enum GNUNET_GenericReturnValue 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:363
void GNUNET_IDENTITY_ego_lookup_cancel(struct GNUNET_IDENTITY_EgoLookup *el)
Abort ego lookup attempt.
Handle for ego lookup.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
enum GNUNET_GenericReturnValue GNUNET_REVOCATION_pow_round(struct GNUNET_REVOCATION_PowCalculationHandle *pc)
Calculate a single round in the key revocation PoW.
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:1331
int GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1459
Struct for a proof of work as part of the revocation.
static struct GNUNET_ATS_PerformanceHandle * ph
ATS performance handle used.
Definition: gnunet-ats.c:116
ssize_t GNUNET_IDENTITY_key_get_length(const struct GNUNET_IDENTITY_PublicKey *key)
Get the compacted length of a GNUNET_IDENTITY_PublicKey.
Definition: identity_api.c:976
#define GNUNET_REVOCATION_MAX_PROOF_SIZE
Maximum length of a revocation.
A private key for an identity as per LSD0001.
enum GNUNET_GenericReturnValue 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.
int main(int argc, char *const *argv)
The main function of gnunet-revocation.
Definition of a command line option.
void GNUNET_IDENTITY_ego_get_public_key(struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_IDENTITY_PublicKey *pk)
Get the identifier (public key) of an ego.
Definition: identity_api.c:652
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:531
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.
static void perform_revocation()
Perform the revocation.
void GNUNET_REVOCATION_pow_stop(struct GNUNET_REVOCATION_PowCalculationHandle *pc)
Stop a PoW calculation.
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:184
static struct GNUNET_TIME_Relative epoch_duration
Epoch length.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1269
Handle for an ego.
Definition: identity.h:36
struct GNUNET_REVOCATION_Query * GNUNET_REVOCATION_query(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_IDENTITY_PublicKey *key, GNUNET_REVOCATION_Callback func, void *func_cls)
Check if a key was revoked.
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:1296
static void sync_pow()
Write the current state of the revocation data to disk.
static void ego_callback(void *cls, struct GNUNET_IDENTITY_Ego *ego)
Function called with the result from the ego lookup.
static struct GNUNET_REVOCATION_PowP * proof_of_work
Proof-of-work object.
static int perform
Was "-p" specified?
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
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.
enum GNUNET_GenericReturnValue GNUNET_IDENTITY_public_key_from_string(const char *str, struct GNUNET_IDENTITY_PublicKey *key)
Parses a (Base32) string representation of the public key.
#define GNUNET_free_nz(ptr)
Wrapper around free.
static char * test_ego
-t option.
static unsigned int pow_passes
Pow passes.
struct GNUNET_REVOCATION_PowCalculationHandle * GNUNET_REVOCATION_pow_start(struct GNUNET_REVOCATION_PowP *pow, int epochs, unsigned int difficulty)
Starts a proof-of-work calculation given the pow object as well as target epochs and difficulty...
Handle for the key revocation query.
size_t GNUNET_REVOCATION_proof_get_size(const struct GNUNET_REVOCATION_PowP *pow)
struct GNUNET_REVOCATION_Handle * GNUNET_REVOCATION_revoke(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_REVOCATION_PowP *pow, GNUNET_REVOCATION_Callback func, void *func_cls)
Perform key revocation.
enum GNUNET_GenericReturnValue GNUNET_DISK_fn_write(const char *fn, const void *buf, size_t buf_size, enum GNUNET_DISK_AccessPermissions mode)
Write a buffer to a file atomically.
Definition: disk.c:705
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.
An identity key as per LSD0001.
static char * revoke_ego
-R option
configuration data
Definition: configuration.c:84
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
static void print_revocation_result(void *cls, int is_valid)
Print the result from a revocation request.
const struct GNUNET_IDENTITY_PrivateKey * GNUNET_IDENTITY_ego_get_private_key(const struct GNUNET_IDENTITY_Ego *ego)
Obtain the ECC key associated with a ego.
Definition: identity_api.c:639
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.
Entry in list of pending tasks.
Definition: scheduler.c:134
Handle for the key revocation operation.
The handle to a PoW calculation.
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_remove(const char *filename)
Remove all files in a directory (rm -rf).
Definition: disk.c:905
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_uint(char shortName, const char *name, const char *argumentHelp, const char *description, unsigned int *val)
Allow user to specify an unsigned int.
void GNUNET_REVOCATION_revoke_cancel(struct GNUNET_REVOCATION_Handle *h)
Cancel key revocation.
void GNUNET_REVOCATION_pow_init(const struct GNUNET_IDENTITY_PrivateKey *key, struct GNUNET_REVOCATION_PowP *pow)
Initializes a fresh PoW computation.
static unsigned long long matching_bits
Number of matching bits required for revocation.
enum GNUNET_GenericReturnValue 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:437
#define GNUNET_malloc(size)
Wrapper around malloc.
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:644
Time for relative time used by GNUnet, in microseconds.
enum GNUNET_GenericReturnValue GNUNET_REVOCATION_check_pow(const struct GNUNET_REVOCATION_PowP *pow, unsigned int matching_bits, struct GNUNET_TIME_Relative epoch_duration)
Check if the given proof-of-work is valid.
#define gettext_noop(String)
Definition: gettext.h:69
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972