-skeletons for transport-ng
[oweals/gnunet.git] / src / revocation / test_revocation.c
1 /*
2    This file is part of GNUnet.
3    Copyright (C) 2009, 2013, 2016 GNUnet e.V.
4
5    GNUnet is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published
7    by the Free Software Foundation; either version 3, or (at your
8    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    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with GNUnet; see the file COPYING.  If not, write to the
17    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18    Boston, MA 02110-1301, USA.
19 */
20 /**
21  * @file revocation/test_revocation.c
22  * @brief base testcase for revocation exchange
23  * @author Matthias Wachs
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_core_service.h"
28 #include "gnunet_identity_service.h"
29 #include "gnunet_revocation_service.h"
30 #include "gnunet_testbed_service.h"
31
32 #define NUM_TEST_PEERS 2
33
34 struct TestPeer
35 {
36   struct GNUNET_TESTBED_Peer *p;
37   struct GNUNET_TESTBED_Operation *identity_op;
38   struct GNUNET_TESTBED_Operation *core_op;
39   struct GNUNET_IDENTITY_Handle *idh;
40   const struct GNUNET_CONFIGURATION_Handle *cfg;
41   const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
42   struct GNUNET_CRYPTO_EcdsaPublicKey pubkey;
43   struct GNUNET_CRYPTO_EcdsaSignature sig;
44   struct GNUNET_IDENTITY_Operation *create_id_op;
45   struct GNUNET_IDENTITY_EgoLookup *ego_lookup;
46   struct GNUNET_REVOCATION_Handle *revok_handle;
47   struct GNUNET_CORE_Handle *ch;
48   uint64_t pow;
49 };
50
51 static struct TestPeer testpeers[2];
52
53 /**
54  * Return value from main, set to 0 on success.
55  */
56 static int ok;
57
58
59 static void
60 do_shutdown (void *cls)
61 {
62   unsigned int c;
63
64   for (c = 0; c < NUM_TEST_PEERS; c++)
65   {
66     if (NULL != testpeers[c].create_id_op)
67     {
68       GNUNET_IDENTITY_cancel (testpeers[c].create_id_op);
69       testpeers[c].create_id_op = NULL;
70     }
71     if (NULL != testpeers[c].ego_lookup)
72     {
73       GNUNET_IDENTITY_ego_lookup_cancel (testpeers[c].ego_lookup);
74       testpeers[c].ego_lookup = NULL;
75     }
76     if (NULL != testpeers[c].revok_handle)
77     {
78       GNUNET_REVOCATION_revoke_cancel (testpeers[c].revok_handle);
79       testpeers[c].revok_handle = NULL;
80     }
81     if (NULL != testpeers[c].identity_op)
82     {
83       GNUNET_TESTBED_operation_done (testpeers[c].identity_op);
84       testpeers[c].identity_op = NULL;
85     }
86     if (NULL != testpeers[c].core_op)
87     {
88       GNUNET_TESTBED_operation_done (testpeers[c].core_op);
89       testpeers[c].core_op = NULL;
90     }
91   }
92 }
93
94
95 static void
96 check_revocation (void *cls);
97
98
99 static void
100 revocation_remote_cb (void *cls,
101                       int is_valid)
102 {
103   static int repeat = 0;
104
105   if (GNUNET_NO == is_valid)
106   {
107     fprintf (stderr,
108              "Local revocation successful\n");
109     ok = 0;
110     GNUNET_SCHEDULER_shutdown ();
111     return;
112   }
113   if (repeat < 10)
114   {
115     repeat++;
116     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
117                                   &check_revocation,
118                                   NULL);
119     return;
120   }
121   fprintf (stderr,
122            "Flooding of revocation failed\n");
123   ok = 2;
124   GNUNET_SCHEDULER_shutdown ();
125 }
126
127
128 static void
129 check_revocation (void *cls)
130 {
131   GNUNET_REVOCATION_query (testpeers[0].cfg,
132                            &testpeers[1].pubkey,
133                            &revocation_remote_cb, NULL);
134 }
135
136
137 static void
138 revocation_cb (void *cls,
139                int is_valid)
140 {
141   testpeers[1].revok_handle = NULL;
142   if (GNUNET_NO == is_valid)
143   {
144     fprintf (stderr,
145              "Revocation successful\n");
146     check_revocation (NULL);
147   }
148 }
149
150
151 static void
152 ego_cb (void *cls,
153         const struct GNUNET_IDENTITY_Ego *ego)
154 {
155   static int completed = 0;
156
157   if ((NULL != ego) && (cls == &testpeers[0]))
158   {
159     testpeers[0].ego_lookup = NULL;
160     testpeers[0].privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
161     GNUNET_IDENTITY_ego_get_public_key (ego, &testpeers[0].pubkey);
162     completed++;
163   }
164   if ((NULL != ego) && (cls == &testpeers[1]))
165   {
166     testpeers[1].ego_lookup = NULL;
167     testpeers[1].privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
168     GNUNET_IDENTITY_ego_get_public_key (ego, &testpeers[1].pubkey);
169     GNUNET_REVOCATION_sign_revocation (testpeers[1].privkey, &testpeers[1].sig);
170
171     GNUNET_log(GNUNET_ERROR_TYPE_INFO,
172                "Calculating proof of work...\n");
173     testpeers[1].pow = 0;
174     int res = GNUNET_REVOCATION_check_pow (&testpeers[1].pubkey,
175         testpeers[1].pow, 5);
176     while (GNUNET_OK != res)
177     {
178       testpeers[1].pow++;
179       res = GNUNET_REVOCATION_check_pow (&testpeers[1].pubkey,
180                                          testpeers[1].pow,
181                                          5);
182     }
183     fprintf (stderr,
184              "Done calculating proof of work\n");
185     completed++;
186   }
187   if (2 == completed)
188   {
189     GNUNET_log(GNUNET_ERROR_TYPE_INFO,
190                "Egos retrieved\n");
191     testpeers[1].revok_handle
192       = GNUNET_REVOCATION_revoke (testpeers[1].cfg,
193                                   &testpeers[1].pubkey,
194                                   &testpeers[1].sig,
195                                   testpeers[1].pow,
196                                   &revocation_cb, NULL);
197   }
198 }
199
200
201 static void
202 identity_create_cb (void *cls,
203                     const char *emsg)
204 {
205   static int completed = 0;
206
207   if ((NULL == emsg) && (cls == &testpeers[0]))
208   {
209     testpeers[0].create_id_op = NULL;
210     completed++;
211   }
212   if ((NULL == emsg) && (cls == &testpeers[1]))
213   {
214     testpeers[1].create_id_op = NULL;
215     completed++;
216   }
217   if (2 != completed)
218     return;
219   fprintf (stderr,
220            "Identities created\n");
221   testpeers[0].ego_lookup = GNUNET_IDENTITY_ego_lookup (testpeers[0].cfg,
222                                                         "client",
223                                                         &ego_cb,
224                                                         &testpeers[0]);
225   testpeers[1].ego_lookup = GNUNET_IDENTITY_ego_lookup (testpeers[1].cfg,
226                                                         "toberevoked",
227                                                         &ego_cb,
228                                                         &testpeers[1]);
229 }
230
231
232 static void
233 identity_completion_cb (void *cls,
234                         struct GNUNET_TESTBED_Operation *op,
235                         void *ca_result,
236                         const char *emsg)
237 {
238   static int completed = 0;
239
240   completed++;
241   if (NUM_TEST_PEERS != completed)
242     return;
243   fprintf (stderr,
244            "All peers connected @ IDENTITY ...\n");
245   testpeers[0].create_id_op
246     = GNUNET_IDENTITY_create (testpeers[0].idh,
247                               "client",
248                               &identity_create_cb,
249                               &testpeers[0]);
250   testpeers[1].create_id_op
251     = GNUNET_IDENTITY_create (testpeers[1].idh,
252                               "toberevoked",
253                               &identity_create_cb,
254                               &testpeers[1]);
255 }
256
257
258 static void *
259 identity_connect_adapter (void *cls,
260                           const struct GNUNET_CONFIGURATION_Handle *cfg)
261 {
262   struct TestPeer *me = cls;
263
264   me->cfg = cfg;
265   me->idh = GNUNET_IDENTITY_connect (cfg, NULL, NULL);
266   if (NULL == me->idh)
267     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
268                 "Failed to create IDENTITY handle \n");
269   return me->idh;
270 }
271
272
273 static void
274 identity_disconnect_adapter (void *cls,
275                              void *op_result)
276 {
277   struct TestPeer *me = cls;
278   GNUNET_IDENTITY_disconnect (me->idh);
279   me->idh = NULL;
280 }
281
282
283 static void
284 connect_cb (void *cls,
285             const struct GNUNET_PeerIdentity *peer)
286 {
287   static int connects = 0;
288
289   connects++;
290   if (NUM_TEST_PEERS * NUM_TEST_PEERS == connects)
291   {
292     fprintf (stderr,
293              "All peers connected @ CORE ...\n");
294
295     /* Connect to identity service */
296     testpeers[0].identity_op
297       = GNUNET_TESTBED_service_connect (NULL,
298                                         testpeers[0].p, "identity",
299                                         &identity_completion_cb, NULL,
300                                         &identity_connect_adapter,
301                                         &identity_disconnect_adapter,
302                                         &testpeers[0]);
303     testpeers[1].identity_op
304       = GNUNET_TESTBED_service_connect (NULL,
305                                         testpeers[1].p, "identity",
306                                         *identity_completion_cb, NULL,
307                                         &identity_connect_adapter,
308                                         &identity_disconnect_adapter,
309                                         &testpeers[1]);
310   }
311 }
312
313
314 static void
315 core_completion_cb (void *cls,
316                     struct GNUNET_TESTBED_Operation *op,
317                     void *ca_result,
318                     const char *emsg)
319 {
320   static int completed = 0;
321
322   completed++;
323   if (NUM_TEST_PEERS == completed)
324   {
325     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
326                 "Connected to CORE\n");
327   }
328 }
329
330
331 static void *
332 core_connect_adapter (void *cls,
333                       const struct GNUNET_CONFIGURATION_Handle *cfg)
334 {
335   struct TestPeer *me = cls;
336
337   me->cfg = cfg;
338   me->ch = GNUNET_CORE_connect (cfg, me, NULL,
339                                 &connect_cb, NULL,
340                                 NULL, GNUNET_NO,
341                                 NULL, GNUNET_NO,
342                                 NULL);
343   if (NULL == me->ch)
344     GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
345                "Failed to create CORE handle \n");
346   return me->ch;
347 }
348
349
350 static void
351 core_disconnect_adapter (void *cls,
352                          void *op_result)
353 {
354   struct TestPeer *me = cls;
355
356   GNUNET_CORE_disconnect (me->ch);
357   me->ch = NULL;
358 }
359
360
361 static void
362 test_connection (void *cls,
363                  struct GNUNET_TESTBED_RunHandle *h,
364                  unsigned int num_peers,
365                  struct GNUNET_TESTBED_Peer **peers,
366                  unsigned int links_succeeded,
367                  unsigned int links_failed)
368 {
369   unsigned int c;
370
371   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
372                                  NULL);
373   if (NUM_TEST_PEERS != num_peers)
374   {
375     ok = 4;
376     fprintf (stderr,
377              "Only %u out of %u peers were started ...\n",
378              num_peers,
379              NUM_TEST_PEERS);
380     GNUNET_SCHEDULER_shutdown ();
381     return;
382   }
383    /* We are generating a CLIQUE */
384   if (NUM_TEST_PEERS * (NUM_TEST_PEERS -1) == links_succeeded)
385   {
386     fprintf (stderr,
387              "Testbed connected peers, initializing test\n");
388     for (c = 0; c < num_peers; c++)
389     {
390       testpeers[c].p = peers[c];
391       testpeers[c].core_op
392         = GNUNET_TESTBED_service_connect (NULL,
393                                           testpeers[c].p,
394                                           "core",
395                                           &core_completion_cb, NULL,
396                                           &core_connect_adapter,
397                                           &core_disconnect_adapter,
398                                           &testpeers[c]);
399     }
400   }
401   else
402   {
403     fprintf (stderr,
404              "Testbed failed to connect peers\n");
405     ok = 5;
406     GNUNET_SCHEDULER_shutdown ();
407     return;
408   }
409 }
410
411
412 int
413 main (int argc,
414       char *argv[])
415 {
416   ok = 1;
417   /* Connecting initial topology */
418   (void) GNUNET_TESTBED_test_run ("test-revocation",
419                                   "test_revocation.conf",
420                                   NUM_TEST_PEERS, 0,
421                                   NULL, NULL,
422                                   &test_connection, NULL);
423   return ok;
424 }
425
426 /* end of test_revocation.c */